import { Cartesian2 } from '../../Source/Cesium.js';
import { Cartesian4 } from '../../Source/Cesium.js';
import { Color } from '../../Source/Cesium.js';
import { Resource } from '../../Source/Cesium.js';
import { Cesium3DTileStyle } from '../../Source/Cesium.js';
import { ConditionsExpression } from '../../Source/Cesium.js';
import { Expression } from '../../Source/Cesium.js';

describe('Scene/Cesium3DTileStyle', function() {

    function MockFeature() {
        this._properties = {};
    }

    MockFeature.prototype.addProperty = function(name, value) {
        this._properties[name] = value;
    };

    MockFeature.prototype.getProperty = function(name) {
        return this._properties[name];
    };

    var feature1 = new MockFeature();
    feature1.addProperty('ZipCode', '19341');
    feature1.addProperty('County', 'Chester');
    feature1.addProperty('YearBuilt', 1979);
    feature1.addProperty('Temperature', 78);
    feature1.addProperty('red', 38);
    feature1.addProperty('green', 255);
    feature1.addProperty('blue', 82);
    feature1.addProperty('volume', 128);
    feature1.addProperty('Height', 100);
    feature1.addProperty('Width', 20);
    feature1.addProperty('Depth', 20);
    feature1.addProperty('id', 11);
    feature1.addProperty('name', 'Hello');

    var feature2 = new MockFeature();
    feature2.addProperty('ZipCode', '19342');
    feature2.addProperty('County', 'Delaware');
    feature2.addProperty('YearBuilt', 1979);
    feature2.addProperty('Temperature', 92);
    feature2.addProperty('red', 255);
    feature2.addProperty('green', 30);
    feature2.addProperty('blue', 30);
    feature2.addProperty('volume', 50);
    feature2.addProperty('Height', 38);
    feature2.addProperty('id', 12);

    var styleUrl = './Data/Cesium3DTiles/Style/style.json';

    it('rejects readyPromise with undefined url', function() {
        var tileStyle = new Cesium3DTileStyle('invalid.json');

        return tileStyle.readyPromise.then(function(style) {
            fail('should not resolve');
        }).otherwise(function(error) {
            expect(tileStyle.ready).toEqual(false);
            expect(error.statusCode).toEqual(404);
        });
    });

    it('loads style from uri', function() {
        var tileStyle = new Cesium3DTileStyle(styleUrl);

        return tileStyle.readyPromise.then(function(style) {
            expect(style.style).toEqual({
                color : "color('red')",
                show : '${id} < 100.0',
                pointSize : '${id} / 100.0',
                pointOutlineColor : "color('blue')",
                pointOutlineWidth : '5.0',
                labelColor : "color('yellow')",
                labelOutlineColor : "color('orange')",
                labelOutlineWidth : '6.0',
                font : "'24px Helvetica'",
                labelStyle : '1',
                labelText : "'label text'",
                backgroundColor : "color('coral')",
                backgroundPadding : 'vec2(1.0, 2.0)',
                backgroundEnabled : 'true',
                scaleByDistance : 'vec4(1.0, 2.0, 3.0, 4.0)',
                translucencyByDistance : 'vec4(5.0, 6.0, 7.0, 8.0)',
                distanceDisplayCondition : 'vec2(3.0, 4.0)',
                heightOffset : '10.0',
                anchorLineEnabled : 'true',
                anchorLineColor : "color('fuchsia')",
                image : "'url/to/invalid/image'",
                disableDepthTestDistance : '1000.0',
                horizontalOrigin : '0',
                verticalOrigin : '0',
                labelHorizontalOrigin : '0',
                labelVerticalOrigin : '0'
            });
            expect(style.color).toEqual(new Expression("color('red')"));
            expect(style.show).toEqual(new Expression('${id} < 100.0'));
            expect(style.pointSize).toEqual(new Expression('${id} / 100.0'));
            expect(style.pointOutlineColor).toEqual(new Expression("color('blue')"));
            expect(style.pointOutlineWidth).toEqual(new Expression('5.0'));
            expect(style.labelColor).toEqual(new Expression("color('yellow')"));
            expect(style.labelOutlineColor).toEqual(new Expression("color('orange')"));
            expect(style.labelOutlineWidth).toEqual(new Expression('6.0'));
            expect(style.font).toEqual(new Expression("'24px Helvetica'"));
            expect(style.labelStyle).toEqual(new Expression('1'));
            expect(style.labelText).toEqual(new Expression("'label text'"));
            expect(style.backgroundColor).toEqual(new Expression("color('coral')"));
            expect(style.backgroundPadding).toEqual(new Expression('vec2(1.0, 2.0)'));
            expect(style.backgroundEnabled).toEqual(new Expression('true'));
            expect(style.scaleByDistance).toEqual(new Expression('vec4(1.0, 2.0, 3.0, 4.0)'));
            expect(style.translucencyByDistance).toEqual(new Expression('vec4(5.0, 6.0, 7.0, 8.0)'));
            expect(style.distanceDisplayCondition).toEqual(new Expression('vec2(3.0, 4.0)'));
            expect(style.heightOffset).toEqual(new Expression('10.0'));
            expect(style.anchorLineEnabled).toEqual(new Expression('true'));
            expect(style.anchorLineColor).toEqual(new Expression("color('fuchsia')"));
            expect(style.image).toEqual(new Expression("'url/to/invalid/image'"));
            expect(style.disableDepthTestDistance).toEqual(new Expression('1000.0'));
            expect(style.horizontalOrigin).toEqual(new Expression('0'));
            expect(style.verticalOrigin).toEqual(new Expression('0'));
            expect(style.labelHorizontalOrigin).toEqual(new Expression('0'));
            expect(style.labelVerticalOrigin).toEqual(new Expression('0'));
            expect(tileStyle.ready).toEqual(true);
        }).otherwise(function() {
            fail('should load style.json');
        });
    });

    it('loads style from Resource', function() {
        var tileStyle = new Cesium3DTileStyle(new Resource({
            url: styleUrl
        }));

        return tileStyle.readyPromise.then(function(style) {
            expect(style.style).toEqual({
                color : "color('red')",
                show : '${id} < 100.0',
                pointSize : '${id} / 100.0',
                pointOutlineColor : "color('blue')",
                pointOutlineWidth : '5.0',
                labelColor : "color('yellow')",
                labelOutlineColor : "color('orange')",
                labelOutlineWidth : '6.0',
                font : "'24px Helvetica'",
                labelStyle : '1',
                labelText : "'label text'",
                backgroundColor : "color('coral')",
                backgroundPadding : 'vec2(1.0, 2.0)',
                backgroundEnabled : 'true',
                scaleByDistance : 'vec4(1.0, 2.0, 3.0, 4.0)',
                translucencyByDistance : 'vec4(5.0, 6.0, 7.0, 8.0)',
                distanceDisplayCondition : 'vec2(3.0, 4.0)',
                heightOffset : '10.0',
                anchorLineEnabled : 'true',
                anchorLineColor : "color('fuchsia')",
                image : "'url/to/invalid/image'",
                disableDepthTestDistance : '1000.0',
                horizontalOrigin : '0',
                verticalOrigin : '0',
                labelHorizontalOrigin : '0',
                labelVerticalOrigin : '0'
            });
            expect(style.color).toEqual(new Expression("color('red')"));
            expect(style.show).toEqual(new Expression('${id} < 100.0'));
            expect(style.pointSize).toEqual(new Expression('${id} / 100.0'));
            expect(style.pointOutlineColor).toEqual(new Expression("color('blue')"));
            expect(style.pointOutlineWidth).toEqual(new Expression('5.0'));
            expect(style.labelColor).toEqual(new Expression("color('yellow')"));
            expect(style.labelOutlineColor).toEqual(new Expression("color('orange')"));
            expect(style.labelOutlineWidth).toEqual(new Expression('6.0'));
            expect(style.font).toEqual(new Expression("'24px Helvetica'"));
            expect(style.labelStyle).toEqual(new Expression('1'));
            expect(style.labelText).toEqual(new Expression("'label text'"));
            expect(style.backgroundColor).toEqual(new Expression("color('coral')"));
            expect(style.backgroundPadding).toEqual(new Expression('vec2(1.0, 2.0)'));
            expect(style.backgroundEnabled).toEqual(new Expression('true'));
            expect(style.scaleByDistance).toEqual(new Expression('vec4(1.0, 2.0, 3.0, 4.0)'));
            expect(style.translucencyByDistance).toEqual(new Expression('vec4(5.0, 6.0, 7.0, 8.0)'));
            expect(style.distanceDisplayCondition).toEqual(new Expression('vec2(3.0, 4.0)'));
            expect(style.heightOffset).toEqual(new Expression('10.0'));
            expect(style.anchorLineEnabled).toEqual(new Expression('true'));
            expect(style.anchorLineColor).toEqual(new Expression("color('fuchsia')"));
            expect(style.image).toEqual(new Expression("'url/to/invalid/image'"));
            expect(style.disableDepthTestDistance).toEqual(new Expression('1000.0'));
            expect(style.horizontalOrigin).toEqual(new Expression('0'));
            expect(style.verticalOrigin).toEqual(new Expression('0'));
            expect(style.labelHorizontalOrigin).toEqual(new Expression('0'));
            expect(style.labelVerticalOrigin).toEqual(new Expression('0'));
            expect(tileStyle.ready).toEqual(true);
        }).otherwise(function() {
            fail('should load style.json');
        });
    });

    it('sets show value to undefined if value not present', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.show).toBeUndefined();

        style = new Cesium3DTileStyle();
        expect(style.show).toBeUndefined();
    });

    it('sets show value to expression', function() {
        var style = new Cesium3DTileStyle({
            show : 'true'
        });
        expect(style.show).toEqual(new Expression('true'));

        style = new Cesium3DTileStyle({
            show : 'false'
        });
        expect(style.show).toEqual(new Expression('false'));

        style = new Cesium3DTileStyle({
            show : '${height} * 10 >= 1000'
        });
        expect(style.show).toEqual(new Expression('${height} * 10 >= 1000'));

        style = new Cesium3DTileStyle({
            show : true
        });
        expect(style.show).toEqual(new Expression('true'));

        style = new Cesium3DTileStyle({
            show : false
        });
        expect(style.show).toEqual(new Expression('false'));
    });

    it('sets show value to conditional', function() {
        var jsonExp = {
            conditions : [
                ['${height} > 2', 'false'],
                ['true', 'true']
            ]
        };

        var style = new Cesium3DTileStyle({
            show : jsonExp
        });
        expect(style.show).toEqual(new ConditionsExpression(jsonExp));
    });

    it('sets show expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        var condExp = new ConditionsExpression({
            conditions : [
                ['${height} > 2', 'false'],
                ['true', 'true']
            ]
        });

        style.show = condExp;
        expect(style.show).toEqual(condExp);

        var exp = new Expression('false');
        style.show = exp;
        expect(style.show).toEqual(exp);
    });

    it('sets show values in setter', function() {
        var defines = {
            'showFactor': 10
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.show = '${height} * ${showFactor} >= 1000';
        expect(style.show).toEqual(new Expression('${height} * ${showFactor} >= 1000', defines));

        style.show = false;
        expect(style.show).toEqual(new Expression('false'));

        var jsonExp = {
            conditions : [
                ['${height} > ${showFactor}', 'false'],
                ['true', 'true']
            ]
        };

        style.show = jsonExp;
        expect(style.show).toEqual(new ConditionsExpression(jsonExp, defines));

        style.show = undefined;
        expect(style.show).toBeUndefined();
    });

    it('sets style.show values in setter', function() {
        var style = new Cesium3DTileStyle({});
        style.show = '${height} * ${showFactor} >= 1000';
        expect(style.style.show).toEqual('${height} * ${showFactor} >= 1000');

        style.show = false;
        expect(style.style.show).toEqual('false');

        var jsonExp = {
            conditions : [
                ['${height} > ${showFactor}', 'false'],
                ['true', 'true']
            ]
        };

        style.show = jsonExp;
        expect(style.style.show).toEqual(jsonExp);

        style.show = undefined;
        expect(style.style.show).toBeUndefined();
    });

    it('sets color value to undefined if value not present', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.color).toBeUndefined();

        style = new Cesium3DTileStyle();
        expect(style.color).toBeUndefined();
    });

    it('sets color value to expression', function() {
        var style = new Cesium3DTileStyle({
            color : 'color("red")'
        });
        expect(style.color).toEqual(new Expression('color("red")'));

        style = new Cesium3DTileStyle({
            color : 'rgba(30, 30, 30, 0.5)'
        });
        expect(style.color).toEqual(new Expression('rgba(30, 30, 30, 0.5)'));

        style = new Cesium3DTileStyle({
            color : '(${height} * 10 >= 1000) ? rgba(0.0, 0.0, 1.0, 0.5) : color("blue")'
        });
        expect(style.color).toEqual(new Expression('(${height} * 10 >= 1000) ? rgba(0.0, 0.0, 1.0, 0.5) : color("blue")'));
    });

    it('sets color value to conditional', function() {
        var jsonExp = {
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("blue")']
            ]
        };

        var style = new Cesium3DTileStyle({
            color : jsonExp
        });
        expect(style.color).toEqual(new ConditionsExpression(jsonExp));
    });

    it('sets color expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        var exp = new Expression('color("red")');
        style.color = exp;
        expect(style.color).toEqual(exp);

        var condExp = new ConditionsExpression({
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("blue")']
            ]
        });

        style.color = condExp;
        expect(style.color).toEqual(condExp);

        style.color = undefined;
        expect(style.color).toBeUndefined();
    });

    it('sets style.color expression in setter', function() {
        var style = new Cesium3DTileStyle();

        var stringExp = 'color("red")';
        style.color = new Expression(stringExp);
        expect(style.style.color).toEqual(stringExp);

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("blue")']
            ]
        };

        style.color = new ConditionsExpression(jsonExp);
        expect(style.style.color).toEqual(jsonExp);

        style.color = undefined;
        expect(style.style.color).toBeUndefined();
    });

    it('sets color values in setter', function() {
        var defines = {
            'targetColor': 'red'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.color = 'color("${targetColor}")';
        expect(style.color).toEqual(new Expression('color("${targetColor}")', defines));

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("${targetColor}")']
            ]
        };

        style.color = jsonExp;
        expect(style.color).toEqual(new ConditionsExpression(jsonExp, defines));
    });

    it('sets style.color values in setter', function() {
        var style = new Cesium3DTileStyle();

        style.color = 'color("${targetColor}")';
        expect(style.style.color).toEqual('color("${targetColor}")');

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("${targetColor}")']
            ]
        };

        style.color = jsonExp;
        expect(style.style.color).toEqual(jsonExp);
    });

    it('sets pointSize value to undefined if value not present', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.pointSize).toBeUndefined();

        style = new Cesium3DTileStyle();
        expect(style.pointSize).toBeUndefined();
    });

    it('sets pointSize value to expression', function() {
        var style = new Cesium3DTileStyle({
            pointSize : '2'
        });
        expect(style.pointSize).toEqual(new Expression('2'));

        style = new Cesium3DTileStyle({
            pointSize : '${height} / 10'
        });
        expect(style.pointSize).toEqual(new Expression('${height} / 10'));

        style = new Cesium3DTileStyle({
            pointSize : 2
        });
        expect(style.pointSize).toEqual(new Expression('2'));
    });

    it('sets pointSize value to conditional', function() {
        var jsonExp = {
            conditions : [
                ['${height} > 2', '1.0'],
                ['true', '2.0']
            ]
        };

        var style = new Cesium3DTileStyle({
            pointSize : jsonExp
        });
        expect(style.pointSize).toEqual(new ConditionsExpression(jsonExp));
    });

    it('sets pointSize expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.pointSize = 2;
        expect(style.pointSize).toEqual(new Expression('2'));

        var exp = new Expression('2');
        style.pointSize = exp;
        expect(style.pointSize).toEqual(exp);

        var condExp = new ConditionsExpression({
            conditions : [
                ['${height} > 2', '1.0'],
                ['true', '2.0']
            ]
        });

        style.pointSize = condExp;
        expect(style.pointSize).toEqual(condExp);

        style.pointSize = undefined;
        expect(style.pointSize).toBeUndefined();
    });

    it('sets style.pointSize expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.pointSize = new Expression('2');
        expect(style.style.pointSize).toEqual('2');

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1.0'],
                ['true', '2.0']
            ]
        };
        style.pointSize = new ConditionsExpression(jsonExp);
        expect(style.style.pointSize).toEqual(jsonExp);

        var customExpression = {
            evaluate: function() { return 1; }
        };
        style.pointSize = customExpression;
        expect(style.style.pointSize).toEqual(customExpression);

        style.pointSize = undefined;
        expect(style.style.pointSize).toBeUndefined();
    });

    it('sets pointSize values in setter', function() {
        var defines = {
            'targetPointSize': '2.0'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.pointSize = 2;
        expect(style.pointSize).toEqual(new Expression('2'));

        style.pointSize = '${targetPointSize} + 1.0';
        expect(style.pointSize).toEqual(new Expression('${targetPointSize} + 1.0', defines));

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1.0'],
                ['true', '${targetPointSize}']
            ]
        };

        style.pointSize = jsonExp;
        expect(style.pointSize).toEqual(new ConditionsExpression(jsonExp, defines));
    });

    it('sets style.pointSize values in setter', function() {
        var defines = {
            'targetPointSize': '2.0'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.pointSize = 2;
        expect(style.style.pointSize).toEqual('2');

        style.pointSize = '${targetPointSize} + 1.0';
        expect(style.style.pointSize).toEqual('${targetPointSize} + 1.0');

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1.0'],
                ['true', '${targetPointSize}']
            ]
        };

        style.pointSize = jsonExp;
        expect(style.style.pointSize).toEqual(jsonExp);
    });

    it('sets pointOutlineColor value to undefined if value not present', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.pointOutlineColor).toBeUndefined();

        style = new Cesium3DTileStyle();
        expect(style.pointOutlineColor).toBeUndefined();
    });

    it('sets pointOutlineColor value to expression', function() {
        var style = new Cesium3DTileStyle({
            pointOutlineColor : 'color("red")'
        });
        expect(style.pointOutlineColor).toEqual(new Expression('color("red")'));

        style = new Cesium3DTileStyle({
            pointOutlineColor : 'rgba(30, 30, 30, 0.5)'
        });
        expect(style.pointOutlineColor).toEqual(new Expression('rgba(30, 30, 30, 0.5)'));

        style = new Cesium3DTileStyle({
            pointOutlineColor : '(${height} * 10 >= 1000) ? rgba(0.0, 0.0, 1.0, 0.5) : color("blue")'
        });
        expect(style.pointOutlineColor).toEqual(new Expression('(${height} * 10 >= 1000) ? rgba(0.0, 0.0, 1.0, 0.5) : color("blue")'));
    });

    it('sets pointOutlineColor value to conditional', function() {
        var jsonExp = {
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("blue")']
            ]
        };

        var style = new Cesium3DTileStyle({
            pointOutlineColor : jsonExp
        });
        expect(style.pointOutlineColor).toEqual(new ConditionsExpression(jsonExp));
    });

    it('sets pointOutlineColor expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        var exp = new Expression('color("red")');
        style.pointOutlineColor = exp;
        expect(style.pointOutlineColor).toEqual(exp);

        var condExp = new ConditionsExpression({
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("blue")']
            ]
        });

        style.pointOutlineColor = condExp;
        expect(style.pointOutlineColor).toEqual(condExp);

        style.pointOutlineColor = undefined;
        expect(style.pointOutlineColor).toBeUndefined();
    });

    it('sets style.pointOutlineColor expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.pointOutlineColor = new Expression('color("red")');
        expect(style.style.pointOutlineColor).toEqual('color("red")');

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("blue")']
            ]
        };

        style.pointOutlineColor = new ConditionsExpression(jsonExp);
        expect(style.style.pointOutlineColor).toEqual(jsonExp);

        var customExpression = {
            evaluate: function() { return Color.RED; },
            evaluateColor: function() { return Color.RED; }
        };
        style.pointOutlineColor = customExpression;
        expect(style.style.pointOutlineColor).toEqual(customExpression);

        style.pointOutlineColor = undefined;
        expect(style.style.pointOutlineColor).toBeUndefined();
    });

    it('sets pointOutlineColor values in setter', function() {
        var defines = {
            'targetColor': 'red'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.pointOutlineColor = 'color("${targetColor}")';
        expect(style.pointOutlineColor).toEqual(new Expression('color("${targetColor}")', defines));

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("${targetColor}")']
            ]
        };

        style.pointOutlineColor = jsonExp;
        expect(style.pointOutlineColor).toEqual(new ConditionsExpression(jsonExp, defines));
    });

    it('sets style.pointOutlineColor values in setter', function() {
        var defines = {
            'targetColor': 'red'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.pointOutlineColor = 'color("${targetColor}")';
        expect(style.style.pointOutlineColor).toEqual('color("${targetColor}")');

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("${targetColor}")']
            ]
        };

        style.pointOutlineColor = jsonExp;
        expect(style.style.pointOutlineColor).toEqual(jsonExp);
    });

    it('sets pointOutlineWidth value to undefined if value not present', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.pointOutlineWidth).toBeUndefined();

        style = new Cesium3DTileStyle();
        expect(style.pointOutlineWidth).toBeUndefined();
    });

    it('sets pointOutlineWidth value to expression', function() {
        var style = new Cesium3DTileStyle({
            pointOutlineWidth : '2'
        });
        expect(style.pointOutlineWidth).toEqual(new Expression('2'));

        style = new Cesium3DTileStyle({
            pointOutlineWidth : '${height} / 10'
        });
        expect(style.pointOutlineWidth).toEqual(new Expression('${height} / 10'));

        style = new Cesium3DTileStyle({
            pointOutlineWidth : 2
        });
        expect(style.pointOutlineWidth).toEqual(new Expression('2'));
    });

    it('sets pointOutlineWidth value to conditional', function() {
        var jsonExp = {
            conditions : [
                ['${height} > 2', '1.0'],
                ['true', '2.0']
            ]
        };

        var style = new Cesium3DTileStyle({
            pointOutlineWidth : jsonExp
        });
        expect(style.pointOutlineWidth).toEqual(new ConditionsExpression(jsonExp));
    });

    it('sets pointOutlineWidth expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.pointOutlineWidth = 2;
        expect(style.pointOutlineWidth).toEqual(new Expression('2'));

        var exp = new Expression('2');
        style.pointOutlineWidth = exp;
        expect(style.pointOutlineWidth).toEqual(exp);

        var condExp = new ConditionsExpression({
            conditions : [
                ['${height} > 2', '1.0'],
                ['true', '2.0']
            ]
        });

        style.pointOutlineWidth = condExp;
        expect(style.pointOutlineWidth).toEqual(condExp);

        style.pointOutlineWidth = undefined;
        expect(style.pointOutlineWidth).toBeUndefined();
    });

    it('sets style.pointOutlineWidth expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.pointOutlineWidth = new Expression('2');
        expect(style.style.pointOutlineWidth).toEqual('2');

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1.0'],
                ['true', '2.0']
            ]
        };
        style.pointOutlineWidth = new ConditionsExpression(jsonExp);
        expect(style.style.pointOutlineWidth).toEqual(jsonExp);

        var customExpression = {
            evaluate: function() { return 1; }
        };
        style.pointOutlineWidth = customExpression;
        expect(style.style.pointOutlineWidth).toEqual(customExpression);

        style.pointOutlineWidth = undefined;
        expect(style.style.pointOutlineWidth).toBeUndefined();
    });

    it('sets pointOutlineWidth values in setter', function() {
        var defines = {
            'targetPointSize': '2.0'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.pointOutlineWidth = 2;
        expect(style.pointOutlineWidth).toEqual(new Expression('2'));

        style.pointOutlineWidth = '${targetPointSize} + 1.0';
        expect(style.pointOutlineWidth).toEqual(new Expression('${targetPointSize} + 1.0', defines));

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1.0'],
                ['true', '${targetPointSize}']
            ]
        };

        style.pointOutlineWidth = jsonExp;
        expect(style.pointOutlineWidth).toEqual(new ConditionsExpression(jsonExp, defines));
    });

    it('sets style.pointOutlineWidth values in setter', function() {
        var defines = {
            'targetPointSize': '2.0'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.pointOutlineWidth = 2;
        expect(style.style.pointOutlineWidth).toEqual('2');

        style.pointOutlineWidth = '${targetPointSize} + 1.0';
        expect(style.style.pointOutlineWidth).toEqual('${targetPointSize} + 1.0');

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1.0'],
                ['true', '${targetPointSize}']
            ]
        };

        style.pointOutlineWidth = jsonExp;
        expect(style.style.pointOutlineWidth).toEqual(jsonExp);
    });

    it('sets labelColor value to undefined if value not present', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.labelColor).toBeUndefined();

        style = new Cesium3DTileStyle();
        expect(style.labelColor).toBeUndefined();
    });

    it('sets labelColor value to expression', function() {
        var style = new Cesium3DTileStyle({
            labelColor : 'color("red")'
        });
        expect(style.labelColor).toEqual(new Expression('color("red")'));

        style = new Cesium3DTileStyle({
            labelColor : 'rgba(30, 30, 30, 0.5)'
        });
        expect(style.labelColor).toEqual(new Expression('rgba(30, 30, 30, 0.5)'));

        style = new Cesium3DTileStyle({
            labelColor : '(${height} * 10 >= 1000) ? rgba(0.0, 0.0, 1.0, 0.5) : color("blue")'
        });
        expect(style.labelColor).toEqual(new Expression('(${height} * 10 >= 1000) ? rgba(0.0, 0.0, 1.0, 0.5) : color("blue")'));
    });

    it('sets labelColor value to conditional', function() {
        var jsonExp = {
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("blue")']
            ]
        };

        var style = new Cesium3DTileStyle({
            labelColor : jsonExp
        });
        expect(style.labelColor).toEqual(new ConditionsExpression(jsonExp));
    });

    it('sets labelColor expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        var exp = new Expression('color("red")');
        style.labelColor = exp;
        expect(style.labelColor).toEqual(exp);

        var condExp = new ConditionsExpression({
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("blue")']
            ]
        });

        style.labelColor = condExp;
        expect(style.labelColor).toEqual(condExp);

        style.labelColor = undefined;
        expect(style.labelColor).toBeUndefined();
    });

    it('sets style.labelColor expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.labelColor = new Expression('color("red")');
        expect(style.style.labelColor).toEqual('color("red")');
        var jsonExp = {
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("blue")']
            ]
        };

        style.labelColor = new ConditionsExpression(jsonExp);
        expect(style.style.labelColor).toEqual(jsonExp);

        var customExpression = {
            evaluate: function() { return Color.RED; },
            evaluateColor: function() { return Color.RED; }
        };
        style.labelColor = customExpression;
        expect(style.style.labelColor).toEqual(customExpression);

        style.labelColor = undefined;
        expect(style.style.labelColor).toBeUndefined();
    });

    it('sets labelColor values in setter', function() {
        var defines = {
            'targetColor': 'red'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.labelColor = 'color("${targetColor}")';
        expect(style.labelColor).toEqual(new Expression('color("${targetColor}")', defines));

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("${targetColor}")']
            ]
        };

        style.labelColor = jsonExp;
        expect(style.labelColor).toEqual(new ConditionsExpression(jsonExp, defines));
    });

    it('sets style.labelColor values in setter', function() {
        var defines = {
            'targetColor': 'red'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.labelColor = 'color("${targetColor}")';
        expect(style.style.labelColor).toEqual('color("${targetColor}")');

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("${targetColor}")']
            ]
        };

        style.labelColor = jsonExp;
        expect(style.style.labelColor).toEqual(jsonExp);
    });

    it('sets labelOutlineColor value to undefined if value not present', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.labelOutlineColor).toBeUndefined();

        style = new Cesium3DTileStyle();
        expect(style.labelOutlineColor).toBeUndefined();
    });

    it('sets labelOutlineColor value to expression', function() {
        var style = new Cesium3DTileStyle({
            labelOutlineColor : 'color("red")'
        });
        expect(style.labelOutlineColor).toEqual(new Expression('color("red")'));

        style = new Cesium3DTileStyle({
            labelOutlineColor : 'rgba(30, 30, 30, 0.5)'
        });
        expect(style.labelOutlineColor).toEqual(new Expression('rgba(30, 30, 30, 0.5)'));

        style = new Cesium3DTileStyle({
            labelOutlineColor : '(${height} * 10 >= 1000) ? rgba(0.0, 0.0, 1.0, 0.5) : color("blue")'
        });
        expect(style.labelOutlineColor).toEqual(new Expression('(${height} * 10 >= 1000) ? rgba(0.0, 0.0, 1.0, 0.5) : color("blue")'));
    });

    it('sets labelOutlineColor value to conditional', function() {
        var jsonExp = {
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("blue")']
            ]
        };

        var style = new Cesium3DTileStyle({
            labelOutlineColor : jsonExp
        });
        expect(style.labelOutlineColor).toEqual(new ConditionsExpression(jsonExp));
    });

    it('sets labelOutlineColor expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        var exp = new Expression('color("red")');
        style.labelOutlineColor = exp;
        expect(style.labelOutlineColor).toEqual(exp);

        var condExp = new ConditionsExpression({
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("blue")']
            ]
        });

        style.labelOutlineColor = condExp;
        expect(style.labelOutlineColor).toEqual(condExp);

        style.labelOutlineColor = undefined;
        expect(style.labelOutlineColor).toBeUndefined();
    });

    it('sets style.labelOutlineColor expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.labelOutlineColor = new Expression('color("red")');
        expect(style.style.labelOutlineColor).toEqual('color("red")');

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("blue")']
            ]
        };

        style.labelOutlineColor = new ConditionsExpression(jsonExp);
        expect(style.style.labelOutlineColor).toEqual(jsonExp);

        var customExpression = {
            evaluate: function() { return Color.RED; },
            evaluateColor: function() { return Color.RED; }
        };
        style.labelOutlineColor = customExpression;
        expect(style.style.labelOutlineColor).toEqual(customExpression);

        style.labelOutlineColor = undefined;
        expect(style.style.labelOutlineColor).toBeUndefined();
    });

    it('sets labelOutlineColor values in setter', function() {
        var defines = {
            'targetColor': 'red'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.labelOutlineColor = 'color("${targetColor}")';
        expect(style.labelOutlineColor).toEqual(new Expression('color("${targetColor}")', defines));

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("${targetColor}")']
            ]
        };

        style.labelOutlineColor = jsonExp;
        expect(style.labelOutlineColor).toEqual(new ConditionsExpression(jsonExp, defines));
    });

    it('sets style.labelOutlineColor values in setter', function() {
        var defines = {
            'targetColor': 'red'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.labelOutlineColor = 'color("${targetColor}")';
        expect(style.style.labelOutlineColor).toEqual('color("${targetColor}")');

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("${targetColor}")']
            ]
        };

        style.labelOutlineColor = jsonExp;
        expect(style.style.labelOutlineColor).toEqual(jsonExp);
    });

    it('sets labelOutlineWidth value to undefined if value not present', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.labelOutlineWidth).toBeUndefined();

        style = new Cesium3DTileStyle();
        expect(style.labelOutlineWidth).toBeUndefined();
    });

    it('sets labelOutlineWidth value to expression', function() {
        var style = new Cesium3DTileStyle({
            labelOutlineWidth : '2'
        });
        expect(style.labelOutlineWidth).toEqual(new Expression('2'));

        style = new Cesium3DTileStyle({
            labelOutlineWidth : '${height} / 10'
        });
        expect(style.labelOutlineWidth).toEqual(new Expression('${height} / 10'));

        style = new Cesium3DTileStyle({
            labelOutlineWidth : 2
        });
        expect(style.labelOutlineWidth).toEqual(new Expression('2'));
    });

    it('sets labelOutlineWidth value to conditional', function() {
        var jsonExp = {
            conditions : [
                ['${height} > 2', '1.0'],
                ['true', '2.0']
            ]
        };

        var style = new Cesium3DTileStyle({
            labelOutlineWidth : jsonExp
        });
        expect(style.labelOutlineWidth).toEqual(new ConditionsExpression(jsonExp));
    });

    it('sets labelOutlineWidth expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.labelOutlineWidth = 2;
        expect(style.labelOutlineWidth).toEqual(new Expression('2'));

        var exp = new Expression('2');
        style.labelOutlineWidth = exp;
        expect(style.labelOutlineWidth).toEqual(exp);

        var condExp = new ConditionsExpression({
            conditions : [
                ['${height} > 2', '1.0'],
                ['true', '2.0']
            ]
        });

        style.labelOutlineWidth = condExp;
        expect(style.labelOutlineWidth).toEqual(condExp);

        style.labelOutlineWidth = undefined;
        expect(style.labelOutlineWidth).toBeUndefined();
    });

    it('sets style.labelOutlineWidth expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.labelOutlineWidth = new Expression('2');
        expect(style.style.labelOutlineWidth).toEqual('2');
        var jsonExp = {
            conditions : [
                ['${height} > 2', '1.0'],
                ['true', '2.0']
            ]
        };
        style.labelOutlineWidth = new ConditionsExpression(jsonExp);
        expect(style.style.labelOutlineWidth).toEqual(jsonExp);

        var customExpression = {
            evaluate: function() { return 1; }
        };
        style.labelOutlineWidth = customExpression;
        expect(style.style.labelOutlineWidth).toEqual(customExpression);

        style.labelOutlineWidth = undefined;
        expect(style.style.labelOutlineWidth).toBeUndefined();
    });

    it('sets labelOutlineWidth values in setter', function() {
        var defines = {
            'targetLabelSize': '2.0'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.labelOutlineWidth = 2;
        expect(style.labelOutlineWidth).toEqual(new Expression('2'));

        style.labelOutlineWidth = '${targetLabelSize} + 1.0';
        expect(style.labelOutlineWidth).toEqual(new Expression('${targetLabelSize} + 1.0', defines));

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1.0'],
                ['true', '${targetLabelSize}']
            ]
        };

        style.labelOutlineWidth = jsonExp;
        expect(style.labelOutlineWidth).toEqual(new ConditionsExpression(jsonExp, defines));
    });

    it('sets style.labelOutlineWidth values in setter', function() {
        var defines = {
            'targetLabelSize': '2.0'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.labelOutlineWidth = 2;
        expect(style.style.labelOutlineWidth).toEqual('2');

        style.labelOutlineWidth = '${targetLabelSize} + 1.0';
        expect(style.style.labelOutlineWidth).toEqual('${targetLabelSize} + 1.0');

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1.0'],
                ['true', '${targetLabelSize}']
            ]
        };

        style.labelOutlineWidth = jsonExp;
        expect(style.style.labelOutlineWidth).toEqual(jsonExp);
    });

    it('sets font value to undefined if value not present', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.font).toBeUndefined();

        style = new Cesium3DTileStyle();
        expect(style.font).toBeUndefined();
    });

    it('sets font value to expression', function() {
        var style = new Cesium3DTileStyle({
            font : '\'24px Helvetica\''
        });
        expect(style.font).toEqual(new Expression('\'24px Helvetica\''));

        style = new Cesium3DTileStyle({
            font : '${font}'
        });
        expect(style.font).toEqual(new Expression('${font}'));

        style = new Cesium3DTileStyle({
            font : '\'24px Helvetica\''
        });
        expect(style.font).toEqual(new Expression('\'24px Helvetica\''));
    });

    it('sets font value to conditional', function() {
        var jsonExp = {
            conditions : [
                ['${height} > 2', '\'30px Helvetica\''],
                ['true', '\'24px Helvetica\'']
            ]
        };

        var style = new Cesium3DTileStyle({
            font : jsonExp
        });
        expect(style.font).toEqual(new ConditionsExpression(jsonExp));
    });

    it('sets font expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.font = '\'24px Helvetica\'';
        expect(style.font).toEqual(new Expression('\'24px Helvetica\''));

        var exp = new Expression('\'24px Helvetica\'');
        style.font = exp;
        expect(style.font).toEqual(exp);

        var condExp = new ConditionsExpression({
            conditions : [
                ['${height} > 2', '\'30px Helvetica\''],
                ['true', '\'24px Helvetica\'']
            ]
        });

        style.font = condExp;
        expect(style.font).toEqual(condExp);

        style.font = undefined;
        expect(style.font).toBeUndefined();
    });

    it('sets style.font expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.font = new Expression('\'24px Helvetica\'');
        expect(style.style.font).toEqual('\'24px Helvetica\'');

        var jsonExp = {
            conditions : [
                ['${height} > 2', '\'30px Helvetica\''],
                ['true', '\'24px Helvetica\'']
            ]
        };

        style.font = new ConditionsExpression(jsonExp);
        expect(style.style.font).toEqual(jsonExp);

        var customExpression = {
            evaluate: function() { return '\'24px Helvetica\''; }
        };
        style.font = customExpression;
        expect(style.style.font).toEqual(customExpression);

        style.font = undefined;
        expect(style.style.font).toBeUndefined();
    });

    it('sets font values in setter', function() {
        var defines = {
            'targetFont': '\'30px Helvetica\''
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.font = '\'24px Helvetica\'';
        expect(style.font).toEqual(new Expression('\'24px Helvetica\''));

        style.font = '${targetFont}';
        expect(style.font).toEqual(new Expression('${targetFont}', defines));

        var jsonExp = {
            conditions : [
                ['${height} > 2', '\'24px Helvetica\''],
                ['true', '${targetFont}']
            ]
        };

        style.font = jsonExp;
        expect(style.font).toEqual(new ConditionsExpression(jsonExp, defines));
    });

    it('sets style.font values in setter', function() {
        var defines = {
            'targetFont': '\'30px Helvetica\''
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.font = '\'24px Helvetica\'';
        expect(style.style.font).toEqual('\'24px Helvetica\'');

        style.font = '${targetFont}';
        expect(style.style.font).toEqual('${targetFont}');

        var jsonExp = {
            conditions : [
                ['${height} > 2', '\'24px Helvetica\''],
                ['true', '${targetFont}']
            ]
        };

        style.font = jsonExp;
        expect(style.style.font).toEqual(jsonExp);
    });

    it('sets labelStyle value to undefined if value not present', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.labelStyle).toBeUndefined();

        style = new Cesium3DTileStyle();
        expect(style.labelStyle).toBeUndefined();
    });

    it('sets labelStyle value to expression', function() {
        var style = new Cesium3DTileStyle({
            labelStyle : '2'
        });
        expect(style.labelStyle).toEqual(new Expression('2'));
    });

    it('sets labelStyle value to conditional', function() {
        var jsonExp = {
            conditions : [
                ['${height} > 2', '1'],
                ['true', '2']
            ]
        };

        var style = new Cesium3DTileStyle({
            labelStyle : jsonExp
        });
        expect(style.labelStyle).toEqual(new ConditionsExpression(jsonExp));
    });

    it('sets labelStyle expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.labelStyle = 2;
        expect(style.labelStyle).toEqual(new Expression('2'));

        var exp = new Expression('2');
        style.labelStyle = exp;
        expect(style.labelStyle).toEqual(exp);

        var condExp = new ConditionsExpression({
            conditions : [
                ['${height} > 2', '1'],
                ['true', '2']
            ]
        });

        style.labelStyle = condExp;
        expect(style.labelStyle).toEqual(condExp);

        style.labelStyle = undefined;
        expect(style.labelStyle).toBeUndefined();
    });

    it('sets style.labelStyle expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.labelStyle = new Expression('2');
        expect(style.style.labelStyle).toEqual('2');

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1'],
                ['true', '2']
            ]
        };
        style.labelStyle = new ConditionsExpression(jsonExp);
        expect(style.style.labelStyle).toEqual(jsonExp);

        var customExpression = {
            evaluate: function() { return 0; }
        };
        style.labelStyle = customExpression;
        expect(style.style.labelStyle).toEqual(customExpression);

        style.labelStyle = undefined;
        expect(style.style.labelStyle).toBeUndefined();
    });

    it('sets labelStyle values in setter', function() {
        var defines = {
            'targetLabelStyle': '2'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.labelStyle = 2;
        expect(style.labelStyle).toEqual(new Expression('2'));

        style.labelStyle = '${targetLabelStyle}';
        expect(style.labelStyle).toEqual(new Expression('${targetLabelStyle}', defines));

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1.0'],
                ['true', '${targetLabelStyle}']
            ]
        };

        style.labelStyle = jsonExp;
        expect(style.labelStyle).toEqual(new ConditionsExpression(jsonExp, defines));
    });

    it('sets style.labelStyle values in setter', function() {
        var defines = {
            'targetLabelStyle': '2'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.labelStyle = 2;
        expect(style.style.labelStyle).toEqual('2');

        style.labelStyle = '${targetLabelStyle}';
        expect(style.style.labelStyle).toEqual('${targetLabelStyle}');

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1.0'],
                ['true', '${targetLabelStyle}']
            ]
        };

        style.labelStyle = jsonExp;
        expect(style.style.labelStyle).toEqual(jsonExp);
    });

    it('sets labelText value to undefined if value not present', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.labelText).toBeUndefined();

        style = new Cesium3DTileStyle();
        expect(style.labelText).toBeUndefined();
    });

    it('sets labelText value to expression', function() {
        var style = new Cesium3DTileStyle({
            labelText : '\'test text\''
        });
        expect(style.labelText).toEqual(new Expression('\'test text\''));

        style = new Cesium3DTileStyle({
            labelText : '${text}'
        });
        expect(style.labelText).toEqual(new Expression('${text}'));

        style = new Cesium3DTileStyle({
            labelText : '\'test text\''
        });
        expect(style.labelText).toEqual(new Expression('\'test text\''));
    });

    it('sets labelText value to conditional', function() {
        var jsonExp = {
            conditions : [
                ['${height} > 2', '\'test text 1\''],
                ['true', '\'test text 2\'']
            ]
        };

        var style = new Cesium3DTileStyle({
            labelText : jsonExp
        });
        expect(style.labelText).toEqual(new ConditionsExpression(jsonExp));
    });

    it('sets labelText expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.labelText = '\'test text\'';
        expect(style.labelText).toEqual(new Expression('\'test text\''));

        var exp = new Expression('\'test text\'');
        style.labelText = exp;
        expect(style.labelText).toEqual(exp);

        var condExp = new ConditionsExpression({
            conditions : [
                ['${height} > 2', '\'test text 1\''],
                ['true', '\'test text 2\'']
            ]
        });

        style.labelText = condExp;
        expect(style.labelText).toEqual(condExp);

        style.labelText = undefined;
        expect(style.labelText).toBeUndefined();
    });

    it('sets style.labelText expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.labelText = new Expression('\'test text\'');
        expect(style.style.labelText).toEqual('\'test text\'');

        var jsonExp = {
            conditions : [
                ['${height} > 2', '\'test text 1\''],
                ['true', '\'test text 2\'']
            ]
        };

        style.labelText = new ConditionsExpression(jsonExp);
        expect(style.style.labelText).toEqual(jsonExp);

        var customExpression = {
            evaluate: function() { return '\'test text 1\''; }
        };
        style.labelText = customExpression;
        expect(style.style.labelText).toEqual(customExpression);

        style.labelText = undefined;
        expect(style.style.labelText).toBeUndefined();
    });

    it('sets labelText values in setter', function() {
        var defines = {
            'targetText': '\'test text 1\''
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.labelText = '\'test text\'';
        expect(style.labelText).toEqual(new Expression('\'test text\''));

        style.labelText = '${targetText}';
        expect(style.labelText).toEqual(new Expression('${targetText}', defines));

        var jsonExp = {
            conditions : [
                ['${height} > 2', '\'test text 2\''],
                ['true', '${targetText}']
            ]
        };

        style.labelText = jsonExp;
        expect(style.labelText).toEqual(new ConditionsExpression(jsonExp, defines));
    });

    it('sets style.labelText values in setter', function() {
        var defines = {
            'targetText': '\'test text 1\''
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.labelText = '\'test text\'';
        expect(style.style.labelText).toEqual('\'test text\'');

        style.labelText = '${targetText}';
        expect(style.style.labelText).toEqual('${targetText}');

        var jsonExp = {
            conditions : [
                ['${height} > 2', '\'test text 2\''],
                ['true', '${targetText}']
            ]
        };

        style.labelText = jsonExp;
        expect(style.style.labelText).toEqual(jsonExp);
    });

    it('sets backgroundColor value to undefined if value not present', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.backgroundColor).toBeUndefined();

        style = new Cesium3DTileStyle();
        expect(style.backgroundColor).toBeUndefined();
    });

    it('sets backgroundColor value to expression', function() {
        var style = new Cesium3DTileStyle({
            backgroundColor : 'color("red")'
        });
        expect(style.backgroundColor).toEqual(new Expression('color("red")'));

        style = new Cesium3DTileStyle({
            backgroundColor : 'rgba(30, 30, 30, 0.5)'
        });
        expect(style.backgroundColor).toEqual(new Expression('rgba(30, 30, 30, 0.5)'));

        style = new Cesium3DTileStyle({
            backgroundColor : '(${height} * 10 >= 1000) ? rgba(0.0, 0.0, 1.0, 0.5) : color("blue")'
        });
        expect(style.backgroundColor).toEqual(new Expression('(${height} * 10 >= 1000) ? rgba(0.0, 0.0, 1.0, 0.5) : color("blue")'));
    });

    it('sets backgroundColor value to conditional', function() {
        var jsonExp = {
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("blue")']
            ]
        };

        var style = new Cesium3DTileStyle({
            backgroundColor : jsonExp
        });
        expect(style.backgroundColor).toEqual(new ConditionsExpression(jsonExp));
    });

    it('sets backgroundColor expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        var exp = new Expression('color("red")');
        style.backgroundColor = exp;
        expect(style.backgroundColor).toEqual(exp);

        var condExp = new ConditionsExpression({
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("blue")']
            ]
        });

        style.backgroundColor = condExp;
        expect(style.backgroundColor).toEqual(condExp);

        style.backgroundColor = undefined;
        expect(style.backgroundColor).toBeUndefined();
    });

    it('sets style.backgroundColor expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.backgroundColor = new Expression('color("red")');
        expect(style.style.backgroundColor).toEqual('color("red")');

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("blue")']
            ]
        };

        style.backgroundColor = new ConditionsExpression(jsonExp);
        expect(style.style.backgroundColor).toEqual(jsonExp);

        var customExpression = {
            evaluate: function() { return Color.RED; },
            evaluateColor: function() { return Color.RED; }
        };
        style.backgroundColor = customExpression;
        expect(style.style.backgroundColor).toEqual(customExpression);

        style.backgroundColor = undefined;
        expect(style.style.backgroundColor).toBeUndefined();
    });

    it('sets backgroundColor values in setter', function() {
        var defines = {
            'targetColor': 'red'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.backgroundColor = 'color("${targetColor}")';
        expect(style.backgroundColor).toEqual(new Expression('color("${targetColor}")', defines));

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("${targetColor}")']
            ]
        };

        style.backgroundColor = jsonExp;
        expect(style.backgroundColor).toEqual(new ConditionsExpression(jsonExp, defines));
    });

    it('sets style.backgroundColor values in setter', function() {
        var defines = {
            'targetColor': 'red'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.backgroundColor = 'color("${targetColor}")';
        expect(style.style.backgroundColor).toEqual('color("${targetColor}")');

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("${targetColor}")']
            ]
        };

        style.backgroundColor = jsonExp;
        expect(style.style.backgroundColor).toEqual(jsonExp);
    });

    it('sets backgroundPadding value to undefined if value not present', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.backgroundPadding).toBeUndefined();

        style = new Cesium3DTileStyle();
        expect(style.backgroundPadding).toBeUndefined();
    });

    it('sets backgroundPadding value to expression', function() {
        var style = new Cesium3DTileStyle({
            backgroundPadding : 'vec2(1.0, 2.0)'
        });
        expect(style.backgroundPadding).toEqual(new Expression('vec2(1.0, 2.0)'));

        style = new Cesium3DTileStyle({
            backgroundPadding : 'vec2(3.0, 4.0)'
        });
        expect(style.backgroundPadding).toEqual(new Expression('vec2(3.0, 4.0)'));

        style = new Cesium3DTileStyle({
            backgroundPadding : '(${height} * 10 >= 1000) ? vec2(1.0, 2.0) : vec2(3.0, 4.0)'
        });
        expect(style.backgroundPadding).toEqual(new Expression('(${height} * 10 >= 1000) ? vec2(1.0, 2.0) : vec2(3.0, 4.0)'));
    });

    it('sets backgroundPadding value to conditional', function() {
        var jsonExp = {
            conditions : [
                ['${height} > 2', 'vec2(1.0, 2.0)'],
                ['true', 'vec2(3.0, 4.0)']
            ]
        };

        var style = new Cesium3DTileStyle({
            backgroundPadding : jsonExp
        });
        expect(style.backgroundPadding).toEqual(new ConditionsExpression(jsonExp));
    });

    it('sets backgroundPadding expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        var exp = new Expression('vec2(1.0, 2.0)');
        style.backgroundPadding = exp;
        expect(style.backgroundPadding).toEqual(exp);

        var condExp = new ConditionsExpression({
            conditions : [
                ['${height} > 2', 'vec2(1.0, 2.0)'],
                ['true', 'vec2(3.0, 4.0)']
            ]
        });

        style.backgroundPadding = condExp;
        expect(style.backgroundPadding).toEqual(condExp);

        style.backgroundPadding = undefined;
        expect(style.backgroundPadding).toBeUndefined();
    });

    it('sets style.backgroundPadding expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.backgroundPadding = new Expression('vec2(1.0, 2.0)');
        expect(style.style.backgroundPadding).toEqual('vec2(1.0, 2.0)');

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'vec2(1.0, 2.0)'],
                ['true', 'vec2(3.0, 4.0)']
            ]
        };

        var customExpression = {
            evaluate: function() { return new Cartesian2(1.0, 2.0); }
        };
        style.labelText = customExpression;
        expect(style.style.labelText).toEqual(customExpression);

        style.backgroundPadding = new ConditionsExpression(jsonExp);
        expect(style.style.backgroundPadding).toEqual(jsonExp);

        style.backgroundPadding = undefined;
        expect(style.style.backgroundPadding).toBeUndefined();
    });

    it('sets backgroundPadding values in setter', function() {
        var defines = {
            'targetPadding': '3.0, 4.0'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.backgroundPadding = 'vec2("${targetPadding}")';
        expect(style.backgroundPadding).toEqual(new Expression('vec2("${targetPadding}")', defines));

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'vec2(1.0, 2.0)'],
                ['true', 'vec2("${targetPadding}")']
            ]
        };

        style.backgroundPadding = jsonExp;
        expect(style.backgroundPadding).toEqual(new ConditionsExpression(jsonExp, defines));
    });

    it('sets style.backgroundPadding values in setter', function() {
        var defines = {
            'targetPadding': '3.0, 4.0'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.backgroundPadding = 'vec2("${targetPadding}")';
        expect(style.style.backgroundPadding).toEqual('vec2("${targetPadding}")');

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'vec2(1.0, 2.0)'],
                ['true', 'vec2("${targetPadding}")']
            ]
        };

        style.backgroundPadding = jsonExp;
        expect(style.style.backgroundPadding).toEqual(jsonExp);
    });

    it('sets backgroundEnabled value to undefined if value not present', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.backgroundEnabled).toBeUndefined();

        style = new Cesium3DTileStyle();
        expect(style.backgroundEnabled).toBeUndefined();
    });

    it('sets backgroundEnabled value to expression', function() {
        var style = new Cesium3DTileStyle({
            backgroundEnabled : 'true'
        });
        expect(style.backgroundEnabled).toEqual(new Expression('true'));

        style = new Cesium3DTileStyle({
            backgroundEnabled : 'false'
        });
        expect(style.backgroundEnabled).toEqual(new Expression('false'));

        style = new Cesium3DTileStyle({
            backgroundEnabled : '${height} * 10 >= 1000'
        });
        expect(style.backgroundEnabled).toEqual(new Expression('${height} * 10 >= 1000'));

        style = new Cesium3DTileStyle({
            backgroundEnabled : true
        });
        expect(style.backgroundEnabled).toEqual(new Expression('true'));

        style = new Cesium3DTileStyle({
            backgroundEnabled : false
        });
        expect(style.backgroundEnabled).toEqual(new Expression('false'));
    });

    it('sets backgroundEnabled value to conditional', function() {
        var jsonExp = {
            conditions : [
                ['${height} > 2', 'false'],
                ['true', 'true']
            ]
        };

        var style = new Cesium3DTileStyle({
            backgroundEnabled : jsonExp
        });
        expect(style.backgroundEnabled).toEqual(new ConditionsExpression(jsonExp));
    });

    it('sets backgroundEnabled expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        var condExp = new ConditionsExpression({
            conditions : [
                ['${height} > 2', 'false'],
                ['true', 'true']
            ]
        });

        style.backgroundEnabled = condExp;
        expect(style.backgroundEnabled).toEqual(condExp);

        var exp = new Expression('false');
        style.backgroundEnabled = exp;
        expect(style.backgroundEnabled).toEqual(exp);
    });

    it('sets style.backgroundEnabled expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.backgroundEnabled = new Expression('false');
        expect(style.style.backgroundEnabled).toEqual('false');

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'false'],
                ['true', 'true']
            ]
        };

        style.backgroundEnabled = new ConditionsExpression(jsonExp);
        expect(style.style.backgroundEnabled).toEqual(jsonExp);

        var customExpression = {
            evaluate: function() { return true; }
        };
        style.backgroundEnabled = customExpression;
        expect(style.style.backgroundEnabled).toEqual(customExpression);
    });

    it('sets backgroundEnabled values in setter', function() {
        var defines = {
            'backgroundFactor': 10
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.backgroundEnabled = '${height} * ${backgroundFactor} >= 1000';
        expect(style.backgroundEnabled).toEqual(new Expression('${height} * ${backgroundFactor} >= 1000', defines));

        style.backgroundEnabled = false;
        expect(style.backgroundEnabled).toEqual(new Expression('false'));

        var jsonExp = {
            conditions : [
                ['${height} > ${backgroundFactor}', 'false'],
                ['true', 'true']
            ]
        };

        style.backgroundEnabled = jsonExp;
        expect(style.backgroundEnabled).toEqual(new ConditionsExpression(jsonExp, defines));

        style.backgroundEnabled = undefined;
        expect(style.backgroundEnabled).toBeUndefined();
    });

    it('sets style.backgroundEnabled values in setter', function() {
        var defines = {
            'backgroundFactor': 10
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.backgroundEnabled = '${height} * ${backgroundFactor} >= 1000';
        expect(style.style.backgroundEnabled).toEqual('${height} * ${backgroundFactor} >= 1000');

        style.backgroundEnabled = false;
        expect(style.style.backgroundEnabled).toEqual('false');

        var jsonExp = {
            conditions : [
                ['${height} > ${backgroundFactor}', 'false'],
                ['true', 'true']
            ]
        };

        style.backgroundEnabled = jsonExp;
        expect(style.style.backgroundEnabled).toEqual(jsonExp);

        style.backgroundEnabled = undefined;
        expect(style.style.backgroundEnabled).toBeUndefined();
    });

    it('sets scaleByDistance value to undefined if value not present', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.scaleByDistance).toBeUndefined();

        style = new Cesium3DTileStyle();
        expect(style.scaleByDistance).toBeUndefined();
    });

    it('sets scaleByDistance value to expression', function() {
        var style = new Cesium3DTileStyle({
            scaleByDistance : 'vec4(1.0, 2.0, 3.0, 4.0)'
        });
        expect(style.scaleByDistance).toEqual(new Expression('vec4(1.0, 2.0, 3.0, 4.0)'));

        style = new Cesium3DTileStyle({
            scaleByDistance : 'vec4(5.0, 6.0, 7.0, 8.0)'
        });
        expect(style.scaleByDistance).toEqual(new Expression('vec4(5.0, 6.0, 7.0, 8.0)'));

        style = new Cesium3DTileStyle({
            scaleByDistance : '(${height} * 10 >= 1000) ? vec4(1.0, 2.0, 3.0, 4.0) : vec4(5.0, 6.0, 7.0, 8.0)'
        });
        expect(style.scaleByDistance).toEqual(new Expression('(${height} * 10 >= 1000) ? vec4(1.0, 2.0, 3.0, 4.0) : vec4(5.0, 6.0, 7.0, 8.0)'));
    });

    it('sets scaleByDistance value to conditional', function() {
        var jsonExp = {
            conditions : [
                ['${height} > 2', 'vec4(1.0, 2.0, 3.0, 4.0)'],
                ['true', 'vec4(5.0, 6.0, 7.0, 8.0)']
            ]
        };

        var style = new Cesium3DTileStyle({
            scaleByDistance : jsonExp
        });
        expect(style.scaleByDistance).toEqual(new ConditionsExpression(jsonExp));
    });

    it('sets scaleByDistance expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        var exp = new Expression('vec4(5.0, 6.0, 7.0, 8.0)');
        style.scaleByDistance = exp;
        expect(style.scaleByDistance).toEqual(exp);

        var condExp = new ConditionsExpression({
            conditions : [
                ['${height} > 2', 'vec4(1.0, 2.0, 3.0, 4.0)'],
                ['true', 'vec4(5.0, 6.0, 7.0, 8.0)']
            ]
        });

        style.scaleByDistance = condExp;
        expect(style.scaleByDistance).toEqual(condExp);

        style.scaleByDistance = undefined;
        expect(style.scaleByDistance).toBeUndefined();
    });

    it('sets style.scaleByDistance expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.scaleByDistance = new Expression('vec4(5.0, 6.0, 7.0, 8.0)');
        expect(style.style.scaleByDistance).toEqual('vec4(5.0, 6.0, 7.0, 8.0)');

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'vec4(1.0, 2.0, 3.0, 4.0)'],
                ['true', 'vec4(5.0, 6.0, 7.0, 8.0)']
            ]
        };

        style.scaleByDistance = new ConditionsExpression(jsonExp);
        expect(style.style.scaleByDistance).toEqual(jsonExp);

        var customExpression = {
            evaluate: function() { return new Cartesian4(1.0, 2.0, 3.0, 4.0); }
        };
        style.scaleByDistance = customExpression;
        expect(style.style.scaleByDistance).toEqual(customExpression);

        style.scaleByDistance = undefined;
        expect(style.style.scaleByDistance).toBeUndefined();
    });

    it('sets scaleByDistance values in setter', function() {
        var defines = {
            'targetScale': '1.0, 2.0, 3.0, 4.'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.scaleByDistance = 'vec4("${targetScale}")';
        expect(style.scaleByDistance).toEqual(new Expression('vec4("${targetScale}")', defines));

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'vec4(5.0, 6.0, 7.0, 8.0)'],
                ['true', 'vec4("${targetScale}")']
            ]
        };

        style.scaleByDistance = jsonExp;
        expect(style.scaleByDistance).toEqual(new ConditionsExpression(jsonExp, defines));
    });

    it('sets style.scaleByDistance values in setter', function() {
        var defines = {
            'targetScale': '1.0, 2.0, 3.0, 4.'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.scaleByDistance = 'vec4("${targetScale}")';
        expect(style.style.scaleByDistance).toEqual('vec4("${targetScale}")');

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'vec4(5.0, 6.0, 7.0, 8.0)'],
                ['true', 'vec4("${targetScale}")']
            ]
        };

        style.scaleByDistance = jsonExp;
        expect(style.style.scaleByDistance).toEqual(jsonExp);
    });

    it('sets distanceDisplayCondition value to undefined if value not present', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.distanceDisplayCondition).toBeUndefined();

        style = new Cesium3DTileStyle();
        expect(style.distanceDisplayCondition).toBeUndefined();
    });

    it('sets distanceDisplayCondition value to expression', function() {
        var style = new Cesium3DTileStyle({
            distanceDisplayCondition : 'vec4(1.0, 2.0, 3.0, 4.0)'
        });
        expect(style.distanceDisplayCondition).toEqual(new Expression('vec4(1.0, 2.0, 3.0, 4.0)'));

        style = new Cesium3DTileStyle({
            distanceDisplayCondition : 'vec4(5.0, 6.0, 7.0, 8.0)'
        });
        expect(style.distanceDisplayCondition).toEqual(new Expression('vec4(5.0, 6.0, 7.0, 8.0)'));

        style = new Cesium3DTileStyle({
            distanceDisplayCondition : '(${height} * 10 >= 1000) ? vec4(1.0, 2.0, 3.0, 4.0) : vec4(5.0, 6.0, 7.0, 8.0)'
        });
        expect(style.distanceDisplayCondition).toEqual(new Expression('(${height} * 10 >= 1000) ? vec4(1.0, 2.0, 3.0, 4.0) : vec4(5.0, 6.0, 7.0, 8.0)'));
    });

    it('sets distanceDisplayCondition value to conditional', function() {
        var jsonExp = {
            conditions : [
                ['${height} > 2', 'vec4(1.0, 2.0, 3.0, 4.0)'],
                ['true', 'vec4(5.0, 6.0, 7.0, 8.0)']
            ]
        };

        var style = new Cesium3DTileStyle({
            distanceDisplayCondition : jsonExp
        });
        expect(style.distanceDisplayCondition).toEqual(new ConditionsExpression(jsonExp));
    });

    it('sets distanceDisplayCondition expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        var exp = new Expression('vec4(5.0, 6.0, 7.0, 8.0)');
        style.distanceDisplayCondition = exp;
        expect(style.distanceDisplayCondition).toEqual(exp);

        var condExp = new ConditionsExpression({
            conditions : [
                ['${height} > 2', 'vec4(1.0, 2.0, 3.0, 4.0)'],
                ['true', 'vec4(5.0, 6.0, 7.0, 8.0)']
            ]
        });

        style.distanceDisplayCondition = condExp;
        expect(style.distanceDisplayCondition).toEqual(condExp);

        style.distanceDisplayCondition = undefined;
        expect(style.distanceDisplayCondition).toBeUndefined();
    });

    it('sets style.distanceDisplayCondition expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.distanceDisplayCondition = new Expression('vec4(5.0, 6.0, 7.0, 8.0)');
        expect(style.style.distanceDisplayCondition).toEqual('vec4(5.0, 6.0, 7.0, 8.0)');

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'vec4(1.0, 2.0, 3.0, 4.0)'],
                ['true', 'vec4(5.0, 6.0, 7.0, 8.0)']
            ]
        };

        style.distanceDisplayCondition = new ConditionsExpression(jsonExp);
        expect(style.style.distanceDisplayCondition).toEqual(jsonExp);

        var customExpression = {
            evaluate: function() { return new Cartesian4(1.0, 2.0, 3.0, 4.0); }
        };
        style.distanceDisplayCondition = customExpression;
        expect(style.style.distanceDisplayCondition).toEqual(customExpression);

        style.distanceDisplayCondition = undefined;
        expect(style.style.distanceDisplayCondition).toBeUndefined();
    });

    it('sets distanceDisplayCondition values in setter', function() {
        var defines = {
            'targetTranslucency': '1.0, 2.0, 3.0, 4.'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.distanceDisplayCondition = 'vec4("${targetTranslucency}")';
        expect(style.distanceDisplayCondition).toEqual(new Expression('vec4("${targetTranslucency}")', defines));

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'vec4(5.0, 6.0, 7.0, 8.0)'],
                ['true', 'vec4("${targetTranslucency}")']
            ]
        };

        style.distanceDisplayCondition = jsonExp;
        expect(style.distanceDisplayCondition).toEqual(new ConditionsExpression(jsonExp, defines));
    });

    it('sets style.distanceDisplayCondition values in setter', function() {
        var defines = {
            'targetTranslucency': '1.0, 2.0, 3.0, 4.'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.distanceDisplayCondition = 'vec4("${targetTranslucency}")';
        expect(style.style.distanceDisplayCondition).toEqual('vec4("${targetTranslucency}")');

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'vec4(5.0, 6.0, 7.0, 8.0)'],
                ['true', 'vec4("${targetTranslucency}")']
            ]
        };

        style.distanceDisplayCondition = jsonExp;
        expect(style.style.distanceDisplayCondition).toEqual(jsonExp);
    });

    it('sets heightOffset value to undefined if value not present', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.heightOffset).toBeUndefined();

        style = new Cesium3DTileStyle();
        expect(style.heightOffset).toBeUndefined();
    });

    it('sets heightOffset value to expression', function() {
        var style = new Cesium3DTileStyle({
            heightOffset : '2'
        });
        expect(style.heightOffset).toEqual(new Expression('2'));

        style = new Cesium3DTileStyle({
            heightOffset : '${height} / 10'
        });
        expect(style.heightOffset).toEqual(new Expression('${height} / 10'));

        style = new Cesium3DTileStyle({
            heightOffset : 2
        });
        expect(style.heightOffset).toEqual(new Expression('2'));
    });

    it('sets heightOffset value to conditional', function() {
        var jsonExp = {
            conditions : [
                ['${height} > 2', '1.0'],
                ['true', '2.0']
            ]
        };

        var style = new Cesium3DTileStyle({
            heightOffset : jsonExp
        });
        expect(style.heightOffset).toEqual(new ConditionsExpression(jsonExp));
    });

    it('sets heightOffset expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.heightOffset = 2;
        expect(style.heightOffset).toEqual(new Expression('2'));

        var exp = new Expression('2');
        style.heightOffset = exp;
        expect(style.heightOffset).toEqual(exp);

        var condExp = new ConditionsExpression({
            conditions : [
                ['${height} > 2', '1.0'],
                ['true', '2.0']
            ]
        });

        style.heightOffset = condExp;
        expect(style.heightOffset).toEqual(condExp);

        style.heightOffset = undefined;
        expect(style.heightOffset).toBeUndefined();
    });

    it('sets style.heightOffset expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.heightOffset = new Expression('2');
        expect(style.style.heightOffset).toEqual('2');

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1.0'],
                ['true', '2.0']
            ]
        };

        style.heightOffset = new ConditionsExpression(jsonExp);
        expect(style.style.heightOffset).toEqual(jsonExp);

        var customExpression = {
            evaluate: function() { return 2; }
        };
        style.heightOffset = customExpression;
        expect(style.style.heightOffset).toEqual(customExpression);

        style.heightOffset = undefined;
        expect(style.style.heightOffset).toBeUndefined();
    });

    it('sets heightOffset values in setter', function() {
        var defines = {
            'targetHeight': '2.0'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.heightOffset = 2;
        expect(style.heightOffset).toEqual(new Expression('2'));

        style.heightOffset = '${targetHeight} + 1.0';
        expect(style.heightOffset).toEqual(new Expression('${targetHeight} + 1.0', defines));

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1.0'],
                ['true', '${targetHeight}']
            ]
        };

        style.heightOffset = jsonExp;
        expect(style.heightOffset).toEqual(new ConditionsExpression(jsonExp, defines));
    });

    it('sets style.heightOffset values in setter', function() {
        var defines = {
            'targetHeight': '2.0'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.heightOffset = '${targetHeight} + 1.0';
        expect(style.style.heightOffset).toEqual('${targetHeight} + 1.0');

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1.0'],
                ['true', '${targetHeight}']
            ]
        };

        style.heightOffset = jsonExp;
        expect(style.style.heightOffset).toEqual(jsonExp);
    });

    it('sets anchorLineEnabled value to undefined if value not present', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.anchorLineEnabled).toBeUndefined();

        style = new Cesium3DTileStyle();
        expect(style.anchorLineEnabled).toBeUndefined();
    });

    it('sets anchorLineEnabled value to expression', function() {
        var style = new Cesium3DTileStyle({
            anchorLineEnabled : 'true'
        });
        expect(style.anchorLineEnabled).toEqual(new Expression('true'));

        style = new Cesium3DTileStyle({
            anchorLineEnabled : 'false'
        });
        expect(style.anchorLineEnabled).toEqual(new Expression('false'));

        style = new Cesium3DTileStyle({
            anchorLineEnabled : '${height} * 10 >= 1000'
        });
        expect(style.anchorLineEnabled).toEqual(new Expression('${height} * 10 >= 1000'));

        style = new Cesium3DTileStyle({
            anchorLineEnabled : true
        });
        expect(style.anchorLineEnabled).toEqual(new Expression('true'));

        style = new Cesium3DTileStyle({
            anchorLineEnabled : false
        });
        expect(style.anchorLineEnabled).toEqual(new Expression('false'));
    });

    it('sets anchorLineEnabled value to conditional', function() {
        var jsonExp = {
            conditions : [
                ['${height} > 2', 'false'],
                ['true', 'true']
            ]
        };

        var style = new Cesium3DTileStyle({
            anchorLineEnabled : jsonExp
        });
        expect(style.anchorLineEnabled).toEqual(new ConditionsExpression(jsonExp));
    });

    it('sets anchorLineEnabled expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        var condExp = new ConditionsExpression({
            conditions : [
                ['${height} > 2', 'false'],
                ['true', 'true']
            ]
        });

        style.anchorLineEnabled = condExp;
        expect(style.anchorLineEnabled).toEqual(condExp);

        var exp = new Expression('false');
        style.anchorLineEnabled = exp;
        expect(style.anchorLineEnabled).toEqual(exp);
    });

    it('sets style.anchorLineEnabled expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.anchorLineEnabled = new Expression('false');
        expect(style.style.anchorLineEnabled).toEqual('false');

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'false'],
                ['true', 'true']
            ]
        };

        style.anchorLineEnabled = new ConditionsExpression(jsonExp);
        expect(style.style.anchorLineEnabled).toEqual(jsonExp);

        var customExpression = {
            evaluate: function() { return true; }
        };
        style.anchorLineEnabled = customExpression;
        expect(style.style.anchorLineEnabled).toEqual(customExpression);
    });

    it('sets anchorLineEnabled values in setter', function() {
        var defines = {
            'anchorFactor': 10
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.anchorLineEnabled = '${height} * ${anchorFactor} >= 1000';
        expect(style.anchorLineEnabled).toEqual(new Expression('${height} * ${anchorFactor} >= 1000', defines));

        style.anchorLineEnabled = false;
        expect(style.anchorLineEnabled).toEqual(new Expression('false'));

        var jsonExp = {
            conditions : [
                ['${height} > ${anchorFactor}', 'false'],
                ['true', 'true']
            ]
        };

        style.anchorLineEnabled = jsonExp;
        expect(style.anchorLineEnabled).toEqual(new ConditionsExpression(jsonExp, defines));

        style.anchorLineEnabled = undefined;
        expect(style.anchorLineEnabled).toBeUndefined();
    });

    it('sets style.anchorLineEnabled values in setter', function() {
        var defines = {
            'anchorFactor': 10
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.anchorLineEnabled = '${height} * ${anchorFactor} >= 1000';
        expect(style.style.anchorLineEnabled).toEqual('${height} * ${anchorFactor} >= 1000');

        style.anchorLineEnabled = false;
        expect(style.style.anchorLineEnabled).toEqual('false');

        var jsonExp = {
            conditions : [
                ['${height} > ${anchorFactor}', 'false'],
                ['true', 'true']
            ]
        };

        style.anchorLineEnabled = jsonExp;
        expect(style.style.anchorLineEnabled).toEqual(jsonExp);

        style.anchorLineEnabled = undefined;
        expect(style.style.anchorLineEnabled).toBeUndefined();
    });

    it('sets anchorLineColor value to undefined if value not present', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.anchorLineColor).toBeUndefined();

        style = new Cesium3DTileStyle();
        expect(style.anchorLineColor).toBeUndefined();
    });

    it('sets anchorLineColor value to expression', function() {
        var style = new Cesium3DTileStyle({
            anchorLineColor : 'color("red")'
        });
        expect(style.anchorLineColor).toEqual(new Expression('color("red")'));

        style = new Cesium3DTileStyle({
            anchorLineColor : 'rgba(30, 30, 30, 0.5)'
        });
        expect(style.anchorLineColor).toEqual(new Expression('rgba(30, 30, 30, 0.5)'));

        style = new Cesium3DTileStyle({
            anchorLineColor : '(${height} * 10 >= 1000) ? rgba(0.0, 0.0, 1.0, 0.5) : color("blue")'
        });
        expect(style.anchorLineColor).toEqual(new Expression('(${height} * 10 >= 1000) ? rgba(0.0, 0.0, 1.0, 0.5) : color("blue")'));
    });

    it('sets anchorLineColor value to conditional', function() {
        var jsonExp = {
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("blue")']
            ]
        };

        var style = new Cesium3DTileStyle({
            anchorLineColor : jsonExp
        });
        expect(style.anchorLineColor).toEqual(new ConditionsExpression(jsonExp));
    });

    it('sets anchorLineColor expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        var exp = new Expression('color("red")');
        style.anchorLineColor = exp;
        expect(style.anchorLineColor).toEqual(exp);

        var condExp = new ConditionsExpression({
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("blue")']
            ]
        });

        style.anchorLineColor = condExp;
        expect(style.anchorLineColor).toEqual(condExp);

        style.anchorLineColor = undefined;
        expect(style.anchorLineColor).toBeUndefined();
    });

    it('sets style.anchorLineColor expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.anchorLineColor = new Expression('color("red")');
        expect(style.style.anchorLineColor).toEqual('color("red")');

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("blue")']
            ]
        };

        style.anchorLineColor = new ConditionsExpression(jsonExp);
        expect(style.style.anchorLineColor).toEqual(jsonExp);

        var customExpression = {
            evaluate: function() { return Color.RED; },
            evaluateColor: function() { return Color.RED; }
        };
        style.anchorLineColor = customExpression;
        expect(style.style.anchorLineColor).toEqual(customExpression);

        style.anchorLineColor = undefined;
        expect(style.style.anchorLineColor).toBeUndefined();
    });

    it('sets anchorLineColor values in setter', function() {
        var defines = {
            'targetColor': 'red'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.anchorLineColor = 'color("${targetColor}")';
        expect(style.anchorLineColor).toEqual(new Expression('color("${targetColor}")', defines));

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("${targetColor}")']
            ]
        };

        style.anchorLineColor = jsonExp;
        expect(style.anchorLineColor).toEqual(new ConditionsExpression(jsonExp, defines));
    });

    it('sets style.anchorLineColor values in setter', function() {
        var defines = {
            'targetColor': 'red'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.anchorLineColor = 'color("${targetColor}")';
        expect(style.style.anchorLineColor).toEqual('color("${targetColor}")');

        var jsonExp = {
            conditions : [
                ['${height} > 2', 'color("cyan")'],
                ['true', 'color("${targetColor}")']
            ]
        };

        style.anchorLineColor = jsonExp;
        expect(style.style.anchorLineColor).toEqual(jsonExp);
    });

    it('sets image value to undefined if value not present', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.image).toBeUndefined();

        style = new Cesium3DTileStyle();
        expect(style.image).toBeUndefined();
    });

    it('sets image value to expression', function() {
        var style = new Cesium3DTileStyle({
            image : '\'url/to/image\''
        });
        expect(style.image).toEqual(new Expression('\'url/to/image\''));

        style = new Cesium3DTileStyle({
            image : '${url}'
        });
        expect(style.image).toEqual(new Expression('${url}'));

        style = new Cesium3DTileStyle({
            image : '\'url/to/image\''
        });
        expect(style.image).toEqual(new Expression('\'url/to/image\''));
    });

    it('sets image value to conditional', function() {
        var jsonExp = {
            conditions : [
                ['${height} > 2', '\'url/to/image1\''],
                ['true', '\'url/to/image2\'']
            ]
        };

        var style = new Cesium3DTileStyle({
            image : jsonExp
        });
        expect(style.image).toEqual(new ConditionsExpression(jsonExp));
    });

    it('sets image expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.image = '\'url/to/image\'';
        expect(style.image).toEqual(new Expression('\'url/to/image\''));

        var exp = new Expression('\'url/to/image\'');
        style.image = exp;
        expect(style.image).toEqual(exp);

        var condExp = new ConditionsExpression({
            conditions : [
                ['${height} > 2', '\'url/to/image1\''],
                ['true', '\'url/to/image2\'']
            ]
        });

        style.image = condExp;
        expect(style.image).toEqual(condExp);

        style.image = undefined;
        expect(style.image).toBeUndefined();
    });

    it('sets style.image expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.image = new Expression('\'url/to/image\'');
        expect(style.style.image).toEqual('\'url/to/image\'');

        var jsonExp = {
            conditions : [
                ['${height} > 2', '\'url/to/image1\''],
                ['true', '\'url/to/image2\'']
            ]
        };

        style.image = new ConditionsExpression(jsonExp);
        expect(style.style.image).toEqual(jsonExp);

        var customExpression = {
            evaluate: function() { return '\'url/to/image1\''; }
        };
        style.image = customExpression;
        expect(style.style.image).toEqual(customExpression);

        style.image = undefined;
        expect(style.style.image).toBeUndefined();
    });

    it('sets image values in setter', function() {
        var defines = {
            'targetUrl': '\'url/to/image1\''
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.image = '\'url/to/image\'';
        expect(style.image).toEqual(new Expression('\'url/to/image\''));

        style.image = '${targetUrl}';
        expect(style.image).toEqual(new Expression('${targetUrl}', defines));

        var jsonExp = {
            conditions : [
                ['${height} > 2', '\'url/to/image2\''],
                ['true', '${targetUrl}']
            ]
        };

        style.image = jsonExp;
        expect(style.image).toEqual(new ConditionsExpression(jsonExp, defines));
    });

    it('sets style.image values in setter', function() {
        var defines = {
            'targetUrl': '\'url/to/image1\''
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.image = '\'url/to/image\'';
        expect(style.style.image).toEqual('\'url/to/image\'');

        style.image = '${targetUrl}';
        expect(style.style.image).toEqual('${targetUrl}');

        var jsonExp = {
            conditions : [
                ['${height} > 2', '\'url/to/image2\''],
                ['true', '${targetUrl}']
            ]
        };

        style.image = jsonExp;
        expect(style.style.image).toEqual(jsonExp);
    });

    it('sets disableDepthTestDistance value to undefined if value not present', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.disableDepthTestDistance).toBeUndefined();

        style = new Cesium3DTileStyle();
        expect(style.disableDepthTestDistance).toBeUndefined();
    });

    it('sets disableDepthTestDistance value to expression', function() {
        var style = new Cesium3DTileStyle({
            disableDepthTestDistance : '2'
        });
        expect(style.disableDepthTestDistance).toEqual(new Expression('2'));

        style = new Cesium3DTileStyle({
            disableDepthTestDistance : '${height} / 10'
        });
        expect(style.disableDepthTestDistance).toEqual(new Expression('${height} / 10'));

        style = new Cesium3DTileStyle({
            disableDepthTestDistance : 2
        });
        expect(style.disableDepthTestDistance).toEqual(new Expression('2'));
    });

    it('sets disableDepthTestDistance value to conditional', function() {
        var jsonExp = {
            conditions : [
                ['${height} > 2', '1.0'],
                ['true', '2.0']
            ]
        };

        var style = new Cesium3DTileStyle({
            disableDepthTestDistance : jsonExp
        });
        expect(style.disableDepthTestDistance).toEqual(new ConditionsExpression(jsonExp));
    });

    it('sets disableDepthTestDistance expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.disableDepthTestDistance = 2;
        expect(style.disableDepthTestDistance).toEqual(new Expression('2'));

        var exp = new Expression('2');
        style.disableDepthTestDistance = exp;
        expect(style.disableDepthTestDistance).toEqual(exp);

        var condExp = new ConditionsExpression({
            conditions : [
                ['${height} > 2', '1.0'],
                ['true', '2.0']
            ]
        });

        style.disableDepthTestDistance = condExp;
        expect(style.disableDepthTestDistance).toEqual(condExp);

        style.disableDepthTestDistance = undefined;
        expect(style.disableDepthTestDistance).toBeUndefined();
    });

    it('sets style.disableDepthTestDistance expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.disableDepthTestDistance = new Expression('2');
        expect(style.style.disableDepthTestDistance).toEqual('2');

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1.0'],
                ['true', '2.0']
            ]
        };

        style.disableDepthTestDistance = new ConditionsExpression(jsonExp);
        expect(style.style.disableDepthTestDistance).toEqual(jsonExp);

        var customExpression = {
            evaluate: function() { return 1.0; }
        };
        style.disableDepthTestDistance = customExpression;
        expect(style.style.disableDepthTestDistance).toEqual(customExpression);

        style.disableDepthTestDistance = undefined;
        expect(style.style.disableDepthTestDistance).toBeUndefined();
    });

    it('sets disableDepthTestDistance values in setter', function() {
        var defines = {
            'targetDistance': '2.0'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.disableDepthTestDistance = 2;
        expect(style.disableDepthTestDistance).toEqual(new Expression('2'));

        style.disableDepthTestDistance = '${targetDistance} + 1.0';
        expect(style.disableDepthTestDistance).toEqual(new Expression('${targetDistance} + 1.0', defines));

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1.0'],
                ['true', '${targetDistance}']
            ]
        };

        style.disableDepthTestDistance = jsonExp;
        expect(style.disableDepthTestDistance).toEqual(new ConditionsExpression(jsonExp, defines));
    });

    it('sets horizontalOrigin value to undefined if value not present', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.horizontalOrigin).toBeUndefined();

        style = new Cesium3DTileStyle();
        expect(style.horizontalOrigin).toBeUndefined();
    });

    it('sets horizontalOrigin value to expression', function() {
        var style = new Cesium3DTileStyle({
            horizontalOrigin : '1'
        });
        expect(style.horizontalOrigin).toEqual(new Expression('1'));
    });

    it('sets horizontalOrigin value to conditional', function() {
        var jsonExp = {
            conditions : [
                ['${height} > 2', '1'],
                ['true', '-1']
            ]
        };

        var style = new Cesium3DTileStyle({
            horizontalOrigin : jsonExp
        });
        expect(style.horizontalOrigin).toEqual(new ConditionsExpression(jsonExp));
    });

    it('sets horizontalOrigin expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.horizontalOrigin = 1;
        expect(style.horizontalOrigin).toEqual(new Expression('1'));

        var exp = new Expression('1');
        style.horizontalOrigin = exp;
        expect(style.horizontalOrigin).toEqual(exp);

        var condExp = new ConditionsExpression({
            conditions : [
                ['${height} > 2', '1'],
                ['true', '-1']
            ]
        });

        style.horizontalOrigin = condExp;
        expect(style.horizontalOrigin).toEqual(condExp);

        style.horizontalOrigin = undefined;
        expect(style.horizontalOrigin).toBeUndefined();
    });

    it('sets style.horizontalOrigin expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.horizontalOrigin = new Expression('1');
        expect(style.style.horizontalOrigin).toEqual('1');

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1'],
                ['true', '-1']
            ]
        };

        style.horizontalOrigin = new ConditionsExpression(jsonExp);
        expect(style.style.horizontalOrigin).toEqual(jsonExp);

        var customExpression = {
            evaluate: function() { return 1; }
        };
        style.horizontalOrigin = customExpression;
        expect(style.style.horizontalOrigin).toEqual(customExpression);

        style.horizontalOrigin = undefined;
        expect(style.style.horizontalOrigin).toBeUndefined();
    });

    it('sets horizontalOrigin values in setter', function() {
        var defines = {
            'targetOrigin': '-1'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.horizontalOrigin = -1;
        expect(style.horizontalOrigin).toEqual(new Expression('-1'));

        style.horizontalOrigin = '${targetOrigin}';
        expect(style.horizontalOrigin).toEqual(new Expression('${targetOrigin}', defines));

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1'],
                ['true', '${targetOrigin}']
            ]
        };

        style.horizontalOrigin = jsonExp;
        expect(style.horizontalOrigin).toEqual(new ConditionsExpression(jsonExp, defines));
    });

    it('sets style.horizontalOrigin values in setter', function() {
        var defines = {
            'targetOrigin': '-1'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.horizontalOrigin = -1;
        expect(style.style.horizontalOrigin).toEqual('-1');

        style.horizontalOrigin = '${targetOrigin}';
        expect(style.style.horizontalOrigin).toEqual('${targetOrigin}');

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1'],
                ['true', '${targetOrigin}']
            ]
        };

        style.horizontalOrigin = jsonExp;
        expect(style.style.horizontalOrigin).toEqual(jsonExp);
    });

    it('sets verticalOrigin value to undefined if value not present', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.verticalOrigin).toBeUndefined();

        style = new Cesium3DTileStyle();
        expect(style.verticalOrigin).toBeUndefined();
    });

    it('sets verticalOrigin value to expression', function() {
        var style = new Cesium3DTileStyle({
            verticalOrigin : '1'
        });
        expect(style.verticalOrigin).toEqual(new Expression('1'));
    });

    it('sets verticalOrigin value to conditional', function() {
        var jsonExp = {
            conditions : [
                ['${height} > 2', '1'],
                ['true', '-1']
            ]
        };

        var style = new Cesium3DTileStyle({
            verticalOrigin : jsonExp
        });
        expect(style.verticalOrigin).toEqual(new ConditionsExpression(jsonExp));
    });

    it('sets verticalOrigin expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.verticalOrigin = 1;
        expect(style.verticalOrigin).toEqual(new Expression('1'));

        var exp = new Expression('1');
        style.verticalOrigin = exp;
        expect(style.verticalOrigin).toEqual(exp);

        var condExp = new ConditionsExpression({
            conditions : [
                ['${height} > 2', '1'],
                ['true', '-1']
            ]
        });

        style.verticalOrigin = condExp;
        expect(style.verticalOrigin).toEqual(condExp);

        style.verticalOrigin = undefined;
        expect(style.verticalOrigin).toBeUndefined();
    });

    it('sets style.styleverticalOrigin expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.verticalOrigin = new Expression('1');
        expect(style.style.verticalOrigin).toEqual('1');

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1'],
                ['true', '-1']
            ]
        };

        style.verticalOrigin = new ConditionsExpression(jsonExp);
        expect(style.style.verticalOrigin).toEqual(jsonExp);

        var customExpression = {
            evaluate: function() { return 1; }
        };
        style.verticalOrigin = customExpression;
        expect(style.style.verticalOrigin).toEqual(customExpression);

        style.verticalOrigin = undefined;
        expect(style.style.verticalOrigin).toBeUndefined();
    });

    it('sets verticalOrigin values in setter', function() {
        var defines = {
            'targetOrigin': '-1'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.verticalOrigin = -1;
        expect(style.verticalOrigin).toEqual(new Expression('-1'));

        style.verticalOrigin = '${targetOrigin}';
        expect(style.verticalOrigin).toEqual(new Expression('${targetOrigin}', defines));

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1'],
                ['true', '${targetOrigin}']
            ]
        };

        style.verticalOrigin = jsonExp;
        expect(style.verticalOrigin).toEqual(new ConditionsExpression(jsonExp, defines));
    });

    it('sets style.verticalOrigin values in setter', function() {
        var defines = {
            'targetOrigin': '-1'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.verticalOrigin = -1;
        expect(style.style.verticalOrigin).toEqual('-1');

        style.verticalOrigin = '${targetOrigin}';
        expect(style.style.verticalOrigin).toEqual('${targetOrigin}');

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1'],
                ['true', '${targetOrigin}']
            ]
        };

        style.verticalOrigin = jsonExp;
        expect(style.style.verticalOrigin).toEqual(jsonExp);
    });

    it('sets labelHorizontalOrigin value to undefined if value not present', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.labelHorizontalOrigin).toBeUndefined();

        style = new Cesium3DTileStyle();
        expect(style.labelHorizontalOrigin).toBeUndefined();
    });

    it('sets labelHorizontalOrigin value to expression', function() {
        var style = new Cesium3DTileStyle({
            labelHorizontalOrigin : '1'
        });
        expect(style.labelHorizontalOrigin).toEqual(new Expression('1'));
    });

    it('sets labelHorizontalOrigin value to conditional', function() {
        var jsonExp = {
            conditions : [
                ['${height} > 2', '1'],
                ['true', '-1']
            ]
        };

        var style = new Cesium3DTileStyle({
            labelHorizontalOrigin : jsonExp
        });
        expect(style.labelHorizontalOrigin).toEqual(new ConditionsExpression(jsonExp));
    });

    it('sets labelHorizontalOrigin expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.labelHorizontalOrigin = 1;
        expect(style.labelHorizontalOrigin).toEqual(new Expression('1'));

        var exp = new Expression('1');
        style.labelHorizontalOrigin = exp;
        expect(style.labelHorizontalOrigin).toEqual(exp);

        var condExp = new ConditionsExpression({
            conditions : [
                ['${height} > 2', '1'],
                ['true', '-1']
            ]
        });

        style.labelHorizontalOrigin = condExp;
        expect(style.labelHorizontalOrigin).toEqual(condExp);

        style.labelHorizontalOrigin = undefined;
        expect(style.labelHorizontalOrigin).toBeUndefined();
    });

    it('sets style.labelHorizontalOrigin expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.labelHorizontalOrigin = new Expression('1');
        expect(style.style.labelHorizontalOrigin).toEqual('1');

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1'],
                ['true', '-1']
            ]
        };

        style.labelHorizontalOrigin = new ConditionsExpression(jsonExp);
        expect(style.style.labelHorizontalOrigin).toEqual(jsonExp);

        var customExpression = {
            evaluate: function() { return 1; }
        };
        style.labelHorizontalOrigin = customExpression;
        expect(style.style.labelHorizontalOrigin).toEqual(customExpression);

        style.labelHorizontalOrigin = undefined;
        expect(style.style.labelHorizontalOrigin).toBeUndefined();
    });

    it('sets labelHorizontalOrigin values in setter', function() {
        var defines = {
            'targetOrigin': '-1'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.labelHorizontalOrigin = -1;
        expect(style.labelHorizontalOrigin).toEqual(new Expression('-1'));

        style.labelHorizontalOrigin = '${targetOrigin}';
        expect(style.labelHorizontalOrigin).toEqual(new Expression('${targetOrigin}', defines));

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1'],
                ['true', '${targetOrigin}']
            ]
        };

        style.labelHorizontalOrigin = jsonExp;
        expect(style.labelHorizontalOrigin).toEqual(new ConditionsExpression(jsonExp, defines));
    });

    it('sets style.labelHorizontalOrigin values in setter', function() {
        var defines = {
            'targetOrigin': '-1'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.labelHorizontalOrigin = -1;
        expect(style.style.labelHorizontalOrigin).toEqual('-1');

        style.labelHorizontalOrigin = '${targetOrigin}';
        expect(style.style.labelHorizontalOrigin).toEqual('${targetOrigin}');

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1'],
                ['true', '${targetOrigin}']
            ]
        };

        style.labelHorizontalOrigin = jsonExp;
        expect(style.style.labelHorizontalOrigin).toEqual(jsonExp);
    });

    it('sets labelVerticalOrigin value to undefined if value not present', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.labelVerticalOrigin).toBeUndefined();

        style = new Cesium3DTileStyle();
        expect(style.labelVerticalOrigin).toBeUndefined();
    });

    it('sets labelVerticalOrigin value to expression', function() {
        var style = new Cesium3DTileStyle({
            labelVerticalOrigin : '1'
        });
        expect(style.labelVerticalOrigin).toEqual(new Expression('1'));
    });

    it('sets labelVerticalOrigin value to conditional', function() {
        var jsonExp = {
            conditions : [
                ['${height} > 2', '1'],
                ['true', '-1']
            ]
        };

        var style = new Cesium3DTileStyle({
            labelVerticalOrigin : jsonExp
        });
        expect(style.labelVerticalOrigin).toEqual(new ConditionsExpression(jsonExp));
    });

    it('sets labelVerticalOrigin expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.labelVerticalOrigin = 1;
        expect(style.labelVerticalOrigin).toEqual(new Expression('1'));

        var exp = new Expression('1');
        style.labelVerticalOrigin = exp;
        expect(style.labelVerticalOrigin).toEqual(exp);

        var condExp = new ConditionsExpression({
            conditions : [
                ['${height} > 2', '1'],
                ['true', '-1']
            ]
        });

        style.labelVerticalOrigin = condExp;
        expect(style.labelVerticalOrigin).toEqual(condExp);

        style.labelVerticalOrigin = undefined;
        expect(style.labelVerticalOrigin).toBeUndefined();
    });

    it('sets style.labelVerticalOrigin expressions in setter', function() {
        var style = new Cesium3DTileStyle();

        style.labelVerticalOrigin = new Expression('1');
        expect(style.style.labelVerticalOrigin).toEqual('1');

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1'],
                ['true', '-1']
            ]
        };

        style.labelVerticalOrigin = new ConditionsExpression(jsonExp);
        expect(style.style.labelVerticalOrigin).toEqual(jsonExp);

        var customExpression = {
            evaluate: function() { return 1; }
        };
        style.labelVerticalOrigin = customExpression;
        expect(style.style.labelVerticalOrigin).toEqual(customExpression);

        style.labelVerticalOrigin = undefined;
        expect(style.style.labelVerticalOrigin).toBeUndefined();
    });

    it('sets labelVerticalOrigin values in setter', function() {
        var defines = {
            'targetOrigin': '-1'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.labelVerticalOrigin = -1;
        expect(style.labelVerticalOrigin).toEqual(new Expression('-1'));

        style.labelVerticalOrigin = '${targetOrigin}';
        expect(style.labelVerticalOrigin).toEqual(new Expression('${targetOrigin}', defines));

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1'],
                ['true', '${targetOrigin}']
            ]
        };

        style.labelVerticalOrigin = jsonExp;
        expect(style.labelVerticalOrigin).toEqual(new ConditionsExpression(jsonExp, defines));
    });

    it('sets style.labelVerticalOrigin values in setter', function() {
        var defines = {
            'targetOrigin': '-1'
        };
        var style = new Cesium3DTileStyle({ 'defines': defines });

        style.labelVerticalOrigin = -1;
        expect(style.style.labelVerticalOrigin).toEqual('-1');

        style.labelVerticalOrigin = '${targetOrigin}';
        expect(style.style.labelVerticalOrigin).toEqual('${targetOrigin}');

        var jsonExp = {
            conditions : [
                ['${height} > 2', '1'],
                ['true', '${targetOrigin}']
            ]
        };

        style.labelVerticalOrigin = jsonExp;
        expect(style.style.labelVerticalOrigin).toEqual(jsonExp);
    });

    it('throws on accessing style if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.style;
        }).toThrowDeveloperError();
    });

    it('throws on accessing color if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.color;
        }).toThrowDeveloperError();
    });

    it('throws on accessing show if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.show;
        }).toThrowDeveloperError();
    });

    it('throws on accessing pointSize if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.pointSize;
        }).toThrowDeveloperError();
    });

    it('throws on accessing pointOutlineColor if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.pointOutlineColor;
        }).toThrowDeveloperError();
    });

    it('throws on accessing pointOutlineWidth if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.pointOutlineWidth;
        }).toThrowDeveloperError();
    });

    it('throws on accessing labelColor if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.labelColor;
        }).toThrowDeveloperError();
    });

    it('throws on accessing labelOutlineColor if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.labelOutlineColor;
        }).toThrowDeveloperError();
    });

    it('throws on accessing labelOutlineWidth if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.labelOutlineWidth;
        }).toThrowDeveloperError();
    });

    it('throws on accessing font if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.font;
        }).toThrowDeveloperError();
    });

    it('throws on accessing labelStyle if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.labelStyle;
        }).toThrowDeveloperError();
    });

    it('throws on accessing labelText if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.labelText;
        }).toThrowDeveloperError();
    });

    it('throws on accessing backgroundColor if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.backgroundColor;
        }).toThrowDeveloperError();
    });

    it('throws on accessing backgroundPadding if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.backgroundPadding;
        }).toThrowDeveloperError();
    });

    it('throws on accessing backgroundEnabled if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.backgroundEnabled;
        }).toThrowDeveloperError();
    });

    it('throws on accessing scaleByDistance if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.scaleByDistance;
        }).toThrowDeveloperError();
    });

    it('throws on accessing translucencyByDistance if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.translucencyByDistance;
        }).toThrowDeveloperError();
    });

    it('throws on accessing distanceDisplayCondition if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.distanceDisplayCondition;
        }).toThrowDeveloperError();
    });

    it('throws on accessing heightOffset if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.heightOffset;
        }).toThrowDeveloperError();
    });

    it('throws on accessing anchorLineEnabled if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.anchorLineEnabled;
        }).toThrowDeveloperError();
    });

    it('throws on accessing anchorLineColor if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.anchorLineColor;
        }).toThrowDeveloperError();
    });

    it('throws on accessing image if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.image;
        }).toThrowDeveloperError();
    });

    it('throws on accessing disableDepthTestDistance if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.disableDepthTestDistance;
        }).toThrowDeveloperError();
    });

    it('throws on accessing horizontalOrigin if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.horizontalOrigin;
        }).toThrowDeveloperError();
    });

    it('throws on accessing verticalOrigin if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.verticalOrigin;
        }).toThrowDeveloperError();
    });

    it('throws on accessing labelHorizontalOrigin if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.labelHorizontalOrigin;
        }).toThrowDeveloperError();
    });

    it('throws on accessing labelVerticalOrigin if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.labelVerticalOrigin;
        }).toThrowDeveloperError();
    });

    it('sets meta properties', function() {
        var style = new Cesium3DTileStyle({
            meta : {
                description : '"Hello, ${name}"'
            }
        });
        expect(style.meta.description.evaluate(feature1)).toEqual('Hello, Hello');

        style = new Cesium3DTileStyle({
            meta : {
                featureColor : 'rgb(${red}, ${green}, ${blue})',
                volume : '${Height} * ${Width} * ${Depth}'
            }
        });
        expect(style.meta.featureColor.evaluateColor(feature1)).toEqual(Color.fromBytes(38, 255, 82));
        expect(style.meta.volume.evaluate(feature1)).toEqual(20 * 20 * 100);
    });

    it('default meta has no properties', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.meta).toEqual({});

        style = new Cesium3DTileStyle({
            meta: {}
        });
        expect(style.meta).toEqual({});
    });

    it('default meta has no properties', function() {
        var style = new Cesium3DTileStyle({});
        expect(style.meta).toEqual({});

        style = new Cesium3DTileStyle({
            meta: {}
        });
        expect(style.meta).toEqual({});
    });

    it('throws on accessing meta if not ready', function() {
        var style = new Cesium3DTileStyle({});
        style._ready = false;

        expect(function() {
            return style.meta;
        }).toThrowDeveloperError();
    });

    // Tests for examples from the style spec

    it('applies default style', function() {
        var style = new Cesium3DTileStyle({
            'show' : 'true',
            'color' : "color('#ffffff')",
            'pointSize' : '1.0'
        });

        expect(style.show.evaluate(undefined)).toEqual(true);
        expect(style.color.evaluateColor(undefined)).toEqual(Color.WHITE);
        expect(style.pointSize.evaluate(undefined)).toEqual(1.0);
    });

    it('applies show style with variable', function() {
        var style = new Cesium3DTileStyle({
            'show' : "${ZipCode} === '19341'"
        });

        expect(style.show.evaluate(feature1)).toEqual(true);
        expect(style.show.evaluate(feature2)).toEqual(false);
    });

    it('applies show style with regexp and variables', function() {
        var style = new Cesium3DTileStyle({
            'show' : "(regExp('^Chest').test(${County})) && (${YearBuilt} >= 1970)"
        });

        expect(style.show.evaluate(feature1)).toEqual(true);
        expect(style.show.evaluate(feature2)).toEqual(false);
    });

    it('applies show style with conditional', function() {
        var style = new Cesium3DTileStyle({
            'show' : {
                'conditions' : [
                    ['(${Height} >= 100.0)', 'false'],
                    ['(${Height} >= 70.0)', 'true'],
                    ['(${Height} >= 50.0)', 'false'],
                    ['(${Height} >= 30.0)', 'true'],
                    ['(${Height} >= 10.0)', 'false'],
                    ['(${Height} >= 1.0)', 'true']
                ]
            }
        });
        expect(style.show.evaluate(feature1)).toEqual(false);
        expect(style.show.evaluate(feature2)).toEqual(true);
    });

    it('applies color style variables', function() {
        var style = new Cesium3DTileStyle({
            'color' : "(${Temperature} > 90) ? color('red') : color('white')"
        });
        expect(style.color.evaluateColor(feature1)).toEqual(Color.WHITE);
        expect(style.color.evaluateColor(feature2)).toEqual(Color.RED);
    });

    it('applies color style with new color', function() {
        var style = new Cesium3DTileStyle({
            'color' : 'rgba(${red}, ${green}, ${blue}, (${volume} > 100 ? 0.5 : 1.0))'
        });
        expect(style.color.evaluateColor(feature1)).toEqual(new Color(38/255, 255/255, 82/255, 0.5));
        expect(style.color.evaluateColor(feature2)).toEqual(new Color(255/255, 30/255, 30/255, 1.0));
    });

    it('applies color style that maps id to color', function() {
        var style = new Cesium3DTileStyle({
            'defines' : {
                'id' : "regExp('^1(\\d)').exec(String(${id}))"
            },
            'color' : {
                'conditions' : [
                    ["${id} === '1'", "color('#FF0000')"],
                    ["${id} === '2'", "color('#00FF00')"],
                    ['true', "color('#FFFFFF')"]
                ]
            }
        });
        expect(style.color.evaluateColor(feature1)).toEqual(Color.RED);
        expect(style.color.evaluateColor(feature2)).toEqual(Color.LIME);
    });

    it('applies color style with conditional', function() {
        var style = new Cesium3DTileStyle({
            'color' : {
                'conditions' : [
                    ['(${Height} >= 100.0)', "color('#0000FF')"],
                    ['(${Height} >= 70.0)', "color('#00FFFF')"],
                    ['(${Height} >= 50.0)', "color('#00FF00')"],
                    ['(${Height} >= 30.0)', "color('#FFFF00')"],
                    ['(${Height} >= 10.0)', "color('#FF0000')"],
                    ['(${Height} >= 1.0)', "color('#FF00FF')"]
                ]
            }
        });
        expect(style.color.evaluateColor(feature1)).toEqual(Color.BLUE);
        expect(style.color.evaluateColor(feature2)).toEqual(Color.YELLOW);
    });

    it('applies pointSize style with variable', function() {
        var style = new Cesium3DTileStyle({
            'pointSize' : '${Temperature} / 10.0'
        });

        expect(style.pointSize.evaluate(feature1)).toEqual(7.8);
        expect(style.pointSize.evaluate(feature2)).toEqual(9.2);
    });

    it('applies pointSize style with regexp and variables', function() {
        var style = new Cesium3DTileStyle({
            'pointSize' : "(regExp('^Chest').test(${County})) ? 2.0 : 1.0"
        });

        expect(style.pointSize.evaluate(feature1)).toEqual(2.0);
        expect(style.pointSize.evaluate(feature2)).toEqual(1.0);
    });

    it('applies pointSize style with conditional', function() {
        var style = new Cesium3DTileStyle({
            'pointSize' : {
                'conditions' : [
                    ['(${Height} >= 100.0)', '6'],
                    ['(${Height} >= 70.0)', '5'],
                    ['(${Height} >= 50.0)', '4'],
                    ['(${Height} >= 30.0)', '3'],
                    ['(${Height} >= 10.0)', '2'],
                    ['(${Height} >= 1.0)', '1']
                ]
            }
        });
        expect(style.pointSize.evaluate(feature1)).toEqual(6);
        expect(style.pointSize.evaluate(feature2)).toEqual(3);
    });

    it('applies with defines', function() {
        var style = new Cesium3DTileStyle({
            'defines' : {
                'halfHeight' : '${Height} / 2',
                'quarterHeight' : '${Height} / 4',
                'halfVolume' : '${volume} / 2'
            },
            'color' : {
                'conditions' : [
                    ['(${halfHeight} >= 25.0)', "color('red')"],
                    ['(${Height} >= 1.0)', "color('blue')"]
                ]
            },
            'show' : '(${quarterHeight} >= 20.0)',
            'pointSize' : '${halfVolume} + ${halfHeight}',
            'meta' : {
                'description' : "'Half height is ' + ${halfHeight}"
            }
        });

        expect(style.color.evaluateColor(feature1)).toEqual(Color.RED);
        expect(style.color.evaluateColor(feature2)).toEqual(Color.BLUE);
        expect(style.show.evaluate(feature1)).toEqual(true);
        expect(style.show.evaluate(feature2)).toEqual(false);
        expect(style.pointSize.evaluate(feature1)).toEqual(114);
        expect(style.pointSize.evaluate(feature2)).toEqual(44);
        expect(style.meta.description.evaluate(feature1)).toEqual('Half height is 50');
        expect(style.meta.description.evaluate(feature2)).toEqual('Half height is 19');
    });

    it('return undefined shader functions when the style is empty', function() {
        // The default color style is white, the default show style is true, and the default pointSize is 1.0,
        // but the generated generated shader functions should just be undefined. We don't want all the points to be white.
        var style = new Cesium3DTileStyle({});
        var colorFunction = style.getColorShaderFunction('getColor', '', {});
        var showFunction = style.getShowShaderFunction('getShow', '', {});
        var pointSizeFunction = style.getPointSizeShaderFunction('getPointSize', '', {});
        expect(colorFunction).toBeUndefined();
        expect(showFunction).toBeUndefined();
        expect(pointSizeFunction).toBeUndefined();
    });
});
